Как заинжектить что-то в конструктор Viewmodel
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Внедрение зависимостей в ViewModel с использованием Dagger Hilt
В современной Android-разработке рекомендуется использовать Dagger Hilt для инъекции зависимостей в ViewModel, так как это официальная библиотека от Google, упрощающая работу с Dagger.
Основные способы инъекции в ViewModel
1. Через конструктор ViewModel (предпочтительный способ)
Hilt автоматически обеспечивает зависимости через конструктор, если класс ViewModel аннотирован @HiltViewModel.
@HiltViewModel
class MyViewModel @Inject constructor(
private val repository: DataRepository,
private val analyticsService: AnalyticsService
) : ViewModel() {
fun fetchData() {
repository.getData()
analyticsService.trackEvent("data_fetched")
}
}
Для работы этого подхода необходимо настроить Hilt в проекте:
// В Application классе
@HiltAndroidApp
class MyApplication : Application()
// В Activity или Fragment
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.fetchData()
}
}
2. Через кастомную фабрику ViewModel
Если вам нужно больше контроля над созданием ViewModel, можно использовать кастомную фабрику:
class CustomViewModelFactory @Inject constructor(
private val repository: DataRepository,
private val preferences: SharedPreferences
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return MyViewModel(repository, preferences) as T
}
}
// Использование в Activity/Fragment
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject
lateinit var viewModelFactory: CustomViewModelFactory
private val viewModel: MyViewModel by viewModels { viewModelFactory }
}
3. Провайдинг зависимостей в модулях Hilt
Для того чтобы Hilt знал, как создавать зависимости, их нужно определить в модулях:
@Module
@InstallIn(ViewModelComponent::class)
object ViewModelModule {
@Provides
fun provideRepository(
apiService: ApiService,
database: AppDatabase
): DataRepository {
return DataRepositoryImpl(apiService, database)
}
@Provides
fun provideApiService(retrofit: Retrofit): ApiService {
return retrofit.create(ApiService::class.java)
}
}
Ключевые аспекты и лучшие практики
@HiltViewModel важные особенности:
- ViewModel аннотированные
@HiltViewModelавтоматически привязаны к жизненному циклу компонента, в котором используются - Hilt генерирует необходимые фабрики ViewModel автоматически
- Зависимости уничтожаются вместе с ViewModel
Область видимости зависимостей:
- Зависимости, определенные в
ViewModelComponent, живут столько же, сколько и сам ViewModel - Для разных сценариев используйте разные компоненты:
@ActivityScoped- для зависимостей, живущих пока живёт Activity@FragmentScoped- для зависимостей Fragment@ViewModelScoped- для зависимостей ViewModel
Пример с Assisted Injection для динамических параметров:
@HiltViewModel
class DetailViewModel @Inject constructor(
private val repository: DataRepository,
@Assisted private val itemId: String
) : ViewModel() {
@AssistedFactory
interface Factory {
fun create(itemId: String): DetailViewModel
}
}
Альтернативные подходы
Без Hilt можно использовать:
- Ручная инъекция через фабрику - как показано выше, но со своим графом зависимостей
- Koin - более легковесная библиотека для DI
- Kodein - еще одна альтернативная библиотека
Важные рекомендации:
- Всегда предпочитайте инъекцию через конструктор для тестируемости
- Избегайте инъекции контекста или объектов, связанных с жизненным циклом UI
- Для сложных сценариев создавайте кастомные фабрики
- Используйте
@Qualifierаннотации для различения однотипных зависимостей
Правильная настройка DI в ViewModel обеспечивает чистую архитектуру, упрощает тестирование и делает код более поддерживаемым. Hilt значительно упрощает этот процесс по сравнению с чистым Dagger, автоматизируя большую часть шаблонного кода.