0Pricing
Android Academy · Урок

Внедрение зависимостей с Hilt

Упростите управление зависимостями с помощью Hilt. Используйте @HiltAndroidApp, @AndroidEntryPoint, @HiltViewModel, @Module, @Provides и области @Singleton.

«Внедрение зависимостей с Hilt» — бесплатный урок Android Academy на CoddyKit. Это урок 6 из 6. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 6 уроков всего.

Что такое внедрение зависимостей?

Внедрение зависимостей (DI) означает передачу объекту всего необходимого вместо самостоятельного создания зависимостей.

Без DI класс создаёт собственные зависимости — это приводит к тесной связанности и усложняет тестирование. При использовании DI зависимости внедряются извне — классы слабо связаны, их легко тестировать и заменять.

Ручное DI и Hilt

Ручное DI работает, но при масштабировании становится неудобным:

// Manual DI — you create and pass everything:
val db = AppDatabase.getInstance(context)
val dao = db.userDao()
val repo = UserRepository(dao)
val factory = UserViewModel.Factory(repo)
val viewModel = ViewModelProvider(this, factory)[UserViewModel::class.java]

// With Hilt:
// Just annotate, Hilt does the wiring
@HiltViewModel
class UserViewModel @Inject constructor(private val repo: UserRepository) : ViewModel()

Добавление Hilt

Добавьте Hilt в свой проект:

// project/build.gradle:
buildscript {
    dependencies {
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.51'
    }
}

// app/build.gradle:
plugins {
    id 'com.google.dagger.hilt.android'
    id 'kotlin-kapt'
}

dependencies {
    implementation 'com.google.dagger:hilt-android:2.51'
    kapt 'com.google.dagger:hilt-android-compiler:2.51'
}

@HiltAndroidApp

Пометьте класс Application аннотацией @HiltAndroidApp. Это точка входа в иерархию компонентов Hilt:

@HiltAndroidApp
class MyApp : Application()

// Also register in AndroidManifest.xml:
// <application android:name=".MyApp" ...>

@AndroidEntryPoint

Добавьте @AndroidEntryPoint к Activity, Fragment и Service, которым требуются внедряемые зависимости:

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject lateinit var analytics: AnalyticsService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        analytics.logEvent("app_open")
    }
}

@AndroidEntryPoint
class HomeFragment : Fragment() {
    // Fragment's parent Activity must also be @AndroidEntryPoint
}

@Inject — внедрение через конструктор

Пометьте конструктор аннотацией @Inject, чтобы указать Hilt, как создавать класс. Hilt автоматически разрешит все параметры:

class UserRepository @Inject constructor(
    private val userDao: UserDao,
    private val apiService: ApiService
) {
    suspend fun getUsers() = userDao.getAll()
    suspend fun syncFromNetwork() {
        val users = apiService.fetchUsers()
        userDao.insertAll(users)
    }
}

// Hilt sees UserRepository needs UserDao and ApiService,
// and automatically creates and injects them.

@HiltViewModel

Пометьте ViewModel аннотацией @HiltViewModel и используйте @Inject constructor. Во Fragment получите его с помощью by viewModels():

@HiltViewModel
class UserViewModel @Inject constructor(
    private val repo: UserRepository
) : ViewModel() {

    val users = repo.getUsersFlow().asLiveData()
}

// In Fragment:
@AndroidEntryPoint
class UserFragment : Fragment() {
    private val viewModel: UserViewModel by viewModels()  // Hilt provides it
}

@Module и @Provides

Если Hilt не может использовать внедрение через конструктор (например, для интерфейсов или сторонних классов), предоставьте экземпляры через @Module:

@Module
@InstallIn(SingletonComponent::class)   // lives for app lifetime
object NetworkModule {

    @Provides
    @Singleton
    fun provideRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://api.example.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    @Provides
    @Singleton
    fun provideApiService(retrofit: Retrofit): ApiService {
        return retrofit.create(ApiService::class.java)
    }
}

@Binds — связывание интерфейса

Используйте @Binds, чтобы указать Hilt, какую реализацию применять для интерфейса:

interface AnalyticsService {
    fun logEvent(name: String)
}

class FirebaseAnalytics @Inject constructor() : AnalyticsService {
    override fun logEvent(name: String) { /* Firebase impl */ }
}

@Module
@InstallIn(SingletonComponent::class)
abstract class AnalyticsModule {

    @Binds
    @Singleton
    abstract fun bindAnalytics(impl: FirebaseAnalytics): AnalyticsService
}

Области действия Hilt

Области действия определяют, как долго существует внедрённый экземпляр:

  • @Singleton — один экземпляр в течение всего времени работы приложения (ApplicationComponent)
  • @ActivityRetainedScoped — сохраняется при изменениях конфигурации
  • @ActivityScoped — один экземпляр для каждой Activity
  • @FragmentScoped — один экземпляр для каждого Fragment
  • @ViewModelScoped — один экземпляр для каждого ViewModel

Тестирование с Hilt

Заменяйте настоящие зависимости имитациями в тестах с помощью поддержки тестирования Hilt:

@HiltAndroidTest
class UserRepositoryTest {

    @get:Rule
    val hiltRule = HiltAndroidRule(this)

    @Inject
    lateinit var repo: UserRepository

    @Before
    fun setUp() {
        hiltRule.inject()
    }

    @Test
    fun usersAreFetched() {
        assertNotNull(repo)
    }
}

Быстрая проверка

Какая аннотация указывает Hilt сгенерировать иерархию компонентов DI для всего приложения?

Повторение: внедрение зависимостей с Hilt

Hilt почти полностью автоматизирует DI в Android:

  • @HiltAndroidApp для класса Application
  • @AndroidEntryPoint для Activity и Fragment
  • @Inject constructor для классов, поддерживающих внедрение
  • @HiltViewModel + @Inject constructor для ViewModels
  • @Module + @Provides для сторонних классов и интерфейсов
  • @Singleton для совместного использования одного экземпляра во всём приложении

Далее: push-уведомления с помощью Firebase Cloud Messaging.

Часто задаваемые вопросы

Урок «Внедрение зависимостей с Hilt» бесплатный?

Да — полный текст урока «Внедрение зависимостей с Hilt» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 6 уроков всего.

Чему я научусь в уроке «Внедрение зависимостей с Hilt»?

Упростите управление зависимостями с помощью Hilt. Используйте @HiltAndroidApp, @AndroidEntryPoint, @HiltViewModel, @Module, @Provides и области @Singleton. Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Android Academy?

Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 6 из 6.

Сколько времени занимает урок «Внедрение зависимостей с Hilt»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Android Academy?

Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. ViewModel и LiveData
  2. База данных Room
  3. Корутины и приостанавливаемые функции
  4. Шаблон репозитория
  5. Компонент навигации
  6. Внедрение зависимостей с Hilt
← Назад к Android Academy