Я использую в своем проекте только dagger2 (не dagger-android). Он отлично работает, чтобы внедрить ViewModel с использованием множественной привязки. Но есть одна проблема с тем, что раньше без dagger2 я использовал тот же экземпляр модели представления, который использовался в активности в нескольких фрагментах (с использованием метода fragment-ktx activityViewModels ()), но теперь, поскольку dagger2 вводит модель представления, он всегда дает новый экземпляр (проверяется с помощью hashCode в каждом фрагменте) модели просмотра для каждого фрагмента, что просто прерывает связь между фрагментами с использованием модели просмотра.
Код фрагмента и модели просмотра приведен ниже:
class MyFragment: Fragment() {
@Inject lateinit var chartViewModel: ChartViewModel
override fun onAttach(context: Context) {
super.onAttach(context)
(activity?.application as MyApp).appComponent.inject(this)
}
}
//-----ChartViewModel class-----
class ChartViewModel @Inject constructor(private val repository: ChartRepository) : BaseViewModel() {
//live data code...
}
Вот код для внедрения зависимости модели представления:
//-----ViewModelKey class-----
@MapKey
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
//-----ViewModelFactory class------
@Singleton
@Suppress("UNCHECKED_CAST")
class ViewModelFactory
@Inject constructor(
private val viewModelMap: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val creator = viewModelMap[modelClass] ?: viewModelMap.asIterable()
.firstOrNull { modelClass.isAssignableFrom(it.key) }?.value
?: throw IllegalArgumentException("Unknown ViewModel class $modelClass")
return try {
creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
//-----ViewModelModule class-----
@Module
abstract class ViewModelModule {
@Binds
internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(ChartViewModel::class)
abstract fun bindChartViewModel(chartViewModel: ChartViewModel): ViewModel
}
Есть ли способ получить один и тот же экземпляр модели представления для нескольких фрагментов, а также в то же время внедрить модель представления во фрагменты. Также есть ли необходимость в методе bindViewModelFactory, поскольку он, кажется, не имеет никакого эффекта в приложении даже без этого метода.
Один обходной путь может заключаться в создании BaseFragment для фрагментов, которые имеют общую модель представления, но он снова будет включать шаблонный код, а также я не большой поклонник BaseFragment / BaseActivity. .
Это сгенерированный код для ChartViewModel, который всегда создает новый экземпляр viewModel:
@SuppressWarnings({
"unchecked",
"rawtypes"
})
public final class ChartViewModel_Factory implements Factory<ChartViewModel> {
private final Provider<ChartRepository> repositoryProvider;
public ChartViewModel_Factory(Provider<ChartRepository> repositoryProvider) {
this.repositoryProvider = repositoryProvider;
}
@Override
public ChartViewModel get() {
return newInstance(repositoryProvider.get());
}
public static ChartViewModel_Factory create(Provider<ChartRepository> repositoryProvider) {
return new ChartViewModel_Factory(repositoryProvider);
}
public static ChartViewModel newInstance(ChartRepository repository) {
return new ChartViewModel(repository);
}
}