【发布时间】:2020-05-23 13:27:01
【问题描述】:
我在我的项目中仅使用 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 的 newInstance:
@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);
}
}
【问题讨论】:
-
简单来说,你为什么不试试“activityViewModels”呢?您希望 2 个片段能够访问同一个 ViewModel 实例,对吗?
标签: android android-fragments viewmodel dagger-2 android-mvvm