Преобразование модели представления для использования инъекции зависимостей Hilt

Вот шаги, которые я проделал, и мои ключевые выводы для преобразования моего новостного приложения для Android на использование инъекции зависимостей hilt

Эта статья была первоначально опубликована на vtsen.hashnode.dev 16 июля 2022 года.

Итак, я выполнил шаги из статьи «Как реализовать Hilt в приложении Android?», чтобы преобразовать приложение Android News для использования инъекции зависимостей Hilt. Отличие предыдущей статьи в том, что в ней не рассматривается инъекция зависимостей View Model.

1. Добавьте зависимости и @HiltAndroidApp.

Начальные шаги по настройке точно такие же, как описано ниже:

  • Установка зависимостей Hilt
  • Добавьте @HiltAndroidApp в класс вашего приложения.

2. Добавьте @HiltViewModel и @Inject Constructor.

Чтобы Hilt создал MainViewModel, вам необходимо аннотировать класс с помощью @HiltViewModel. @Inject constructor также используется, чтобы сообщить Hilt, как могут быть созданы зависимости.

@HiltViewModel
class MainViewModel
    @Inject constructor(
        private val repository: ArticlesRepository,
    ) : ViewModel() {
    ...
}
Вход в полноэкранный режим Выход из полноэкранного режима

Я также использую @Inject Constructor на SqlArticlesRepository.

class SqlArticlesRepository @Inject constructor(
    private val database: ArticlesDatabase,
    private val webService: WebService,
) : ArticlesRepository {
   ...
}
Вход в полноэкранный режим Выход из полноэкранного режима

3. Добавьте @Provides и @Binds.

Для создания зависимостей мы используем либо @Provides, либо @Binds. @Provides используется для создания экземпляров ArticlesDatabase и WebService.

@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {

    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext appContext: Context): ArticlesDatabase {

        return Room.databaseBuilder(
            appContext,
            ArticlesDatabase::class.java,
            "articles.db",
        )
            .fallbackToDestructiveMigration()
            .build()
    }
}

@Module
@InstallIn(SingletonComponent::class)
object WebServiceModule {

    @Provides
    @Singleton
    fun provideWebService(): WebService {
        return WebService()
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

@Binds используется для создания реализации интерфейса ArticlesRepository.

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

    @Binds
    @Singleton
    abstract fun bindArticlesRepository(impl: SqlArticlesRepository): ArticlesRepository
}
Вход в полноэкранный режим Выход из полноэкранного режима

4. Вызовите hiltViewModel() Composable

Теперь все готово! Все ручные создания ниже в MainActivity могут быть удалены.

private val repository by lazy {
    SqlArticlesRepository(
        ArticlesDatabase.getInstance(application),
        WebService(),
    )
}

private val homeViewModel by viewModels<MainViewModel> {
    MainViewModelFactory(repository)
}
Вход в полноэкранный режим Выход из полноэкранного режима

Создание MainViewModel можно выполнить, вызвав композитную функцию hiltViewModel(), которая генерирует все необходимые зависимости.

Например, замените эту функцию MainScreen композитной функцией

MainScreen(homeViewModel, useSystemUIController = true)
Вход в полноэкранный режим Выйти из полноэкранного режима

на

MainScreen(viewModel = hiltViewModel(), useSystemUIController = true)
Войти в полноэкранный режим Выйти из полноэкранного режима

Создание базы данных ниже также может быть удалено, поскольку оно было предоставлено hilt @Provides выше.

companion object {
    @Volatile
    private lateinit var instance: ArticlesDatabase

    fun getInstance(context: Context): ArticlesDatabase {
        synchronized(this) {
            if (!::instance.isInitialized) {
                instance = Room.databaseBuilder(
                    context.applicationContext,
                    ArticlesDatabase::class.java,
                    "articles.db")
                    .fallbackToDestructiveMigration()
                    .build()
            }

            return instance
        }
    }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Этот MainViewModelFactory также может быть удален, поскольку об этом позаботился @HiltViewModel.

@Suppress("UNCHECKED_CAST")
class MainViewModelFactory(private val repository: ArticlesRepository)
    : ViewModelProvider.NewInstanceFactory() {

    override fun <T : ViewModel> create(modelClass: Class<T>): T {

        if (modelClass.isAssignableFrom(MainViewModel::class.java)) {
            return MainViewModel(repository) as T
        }

        throw IllegalArgumentException("Unknown ViewModel class")
    }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Заключение

Все мои установленные модули Hilt находятся в области SingletonComponent. Если я меняю установленный модуль на другой компонент, например, ViewModelComponent или ActivityComponent, он не компилируется, и я не знаю, как это исправить. Думаю, это мой следующий шаг в работе с этим Hilt.

Да, мне все еще не нравится Hilt. Называйте меня великим папой, но я все еще предпочитаю ручной ввод зависимостей, как этот:

  • Рекомендуемые способы создания ViewModel или AndroidViewModel

Исходный код

  • Репозиторий GitHub: Android News (ветка Hilt)
  • Разница между ветками: Master vs Hilt

Смотрите также

  • Советы и рекомендации по разработке Android

Оцените статью
devanswers.ru
Добавить комментарий