我正在转换我的应用程序以使用ViewModel
s。为了实例化ViewModel
,我使用自定义Factory
和 Dagger 2 进行依赖注入。它看起来像这样:
@Singleton
class ViewModelFactory @Inject constructor(
private val viewModels: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T
= viewModels[modelClass]!!.get() as T
}
@Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.RUNTIME) @MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
@Module
abstract class ViewModelModule {
@Binds
abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@Binds @IntoMap @ViewModelKey(FooViewModel::class)
abstract fun fooViewModel(viewModel: FooViewModel): ViewModel
}
现在我面临着一个问题,如何在ViewModel
内访问我的Fragment
或Activity
的参数/附加Bundle
。这是必要的,因为ViewModel
中的视图和数据通常是可参数化的。我将如何使用最少的样板来实现这一点?
如果使用"保存状态"模块,则可以通过 SavedStateHandle 获得活动意图附加功能和片段参数
class SavedStateViewModel(private val state: SavedStateHandle) : ViewModel() {
init {
val someArgument = state.get<String>("someArgumentKey")
...
}
}
您还可以使用 AssistedInject 库将参数从活动/片段传递到 ViewModel,但它是一个样板解决方案。这是一个dagger的例子,另一个使用dagger剑柄的例子。
将此类额外内容/参数注入您的视图模型怎么样?您可以通过使用dagger访问此类活动/片段来实现此目的。
@Module
class IntentModule {
@Provides
fun retriveIntentWithExtraX(activity: DestinationActivity): Long {
return activity.intent.getSerializableExtra(SOME_EXTRA_DATA) as Long
}
}
在模块内部包含您的活动/片段:
@Module
abstract class ActivityModules {
@ContributesAndroidInjector(modules = [IntentModule::class])
abstract fun contributeDestinationActivity(): DestinationActivity
}
最后,您可以将这样的参数/额外注入到您的 ViewModels 中,如下所示:
class SomeViewModel @Inject constructor(
private val someExtraData: Long
) : ViewModel()