Hilt: кратчайшее руководство по фреймворку DI для Android

hilt
В поисках надежной, но простой структуры внедрения зависимостей (DI),  не так давно я пришел к выводу, что Koin – это структура DI, которая отвечает моим требованиям. Также, на мой взгляд, Dagger – это де-факто основной фреймворк DI в Android, мощный и популярный – но его нельзя назвать простым. Затем пришел Hilt , который попадает в золотую середину. Это в значительной степени все тот же Dagger (со всей его скоростью и безопасностью во время компиляци), но переделанный во что-то более быстрое и легкое.

Я постараюсь дать очень быстрый обзор того, как использовать Hilt в вашем проекте. Я сделал это в одном из моих существующих проектов и был восхищен тем, насколько это просто.

Настройка

Hilt прост в использовании, потому что он выполняет много “магии” (то есть кодогенерации) “под капотом”. Чтобы начать его использовать, вам необходимо добавить обработчики аннотаций и другие зависимости в файл build.gradle вашего проекта.

Обратитесь к официальной документации, так как вам понадобится довольно много дополнительной информации.

Зависимости

Чтобы сделать класс внедряемым, просто добавьте к конструктору аннотацию @Inject.

class MyHelper @Inject constructor() { 
    [...] 
}

Каждый раз, когда это выполняется, будет создан новый экземпляр. Для внедрения того же самого единственного экземпляра (который будет создан в первый раз), аннотируйте его –  @Singleton.

@Singleton
class MyHelper @Inject constructor() { 
    [...] 
}

Также доступна область видимости для views / фрагментов / активити/ view-models ( документация ). Это означает, что при запросе injections будет возвращен тот же экземпляр, если он находится в том же компоненте. Например, следующий класс будет создаваться каждый раз, когда он запрашивается из нового фрагмента:

@FragmentScoped
class MyHelper @Inject constructor() { 
    [...] 
}

Модули

Если у вас есть интерфейс и реализация, вам понадобится модуль. Думайте об этом как о инструкциях по созданию экземпляра класса. Для простого использования интерфейса / реализации используйте @Binds.

@InstallIn(ApplicationComponent::class)
abstract class MyHelperModule {
  @Binds
  abstract fun bindMyHelper(myHelperImpl: MyHelperImpl): MyHelper
}

Для более сложных «инструкций» используйте @ProvidesContextпредоставляется по умолчанию, если вы добавляете аннотацию с помощью @ApplicationContextили @ActivityContext.

@Module
@InstallIn(ApplicationComponent::class)
object MyHelperModule {

  @Provides
  fun provideMyHelper(
    @ApplicationContext context: Context
  ) {
      [...]
      return MyHelper(context)
  }
}

Место использования @InstallIn вместе с вышеуказанной аннотацией области видимости, определяет, когда будет создан и предоставлен новый экземпляр вашего класса. Например, это создаст новый экземпляр MyHelper для каждого Activity, которое выполняет запрос:

@Module
@InstallIn(ActivityComponent::class)
abstract class MyHelperModule {

  @ActivityScoped
  @Binds
  abstract fun bindMyHelper(myHelper: MyHelperImpl): MyHelper
}

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

Теперь вы определили, какие у вас зависимости. Пришло время внедрить и использовать их.

Для ваших классов, которые вы можете создать, используйте конструктор с аннотацией @Inject (как мы видели выше).

class MyHelper @Inject constructor(private val toBeInjected: AnotherHelper) { 
    [...] 
}

Для системных классов, которые не инстанцируются вами (например, Activities, Fragments, Services), используйте аннотации @AndroidEntryPoint@Inject и механизм lateinit.

@AndroidEntryPoint
class MyActivity : AppCompatActivity() {

  @Inject lateinit var myHelper: MyHelper
  [...]
}

ViewModels

Для внедрения зависимостей ViewModel из Android Jetpack нужен немного другой подход.

Сначала установите эти дополнительные зависимости .

Затем используйте @ViewModelInject (вместо простого @Inject) в конструкторе. Чтобы внедрить SavedStateHandle, добавьте аннотацию @Assisted. Наконец, нет необходимости в какой-либо фабрике ViewModel, используйте by viewModels() для извлечения ViewModelвашего фрагмента или активити.

class MyViewModel @ViewModelInject constructor(
  @Assisted private val savedState: SavedStateHandle,
  private val myHelper: MyHelper,
) : ViewModel() {
  [...]
}

Надеюсь, в этом коротком посте я дал вам некоторое представление о Hilt и о том, как его использовать. Глубокое погружение в документациию даст возможность для более подробного рассмотрения случаев использования. Удачного кодирования!
Источник

Додати коментар