如何使用 Dagger 2 以最少的样板访问 ViewModel 中的参数/附加bundle?



我正在转换我的应用程序以使用ViewModels。为了实例化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内访问我的FragmentActivity的参数/附加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() 

最新更新