首页 > 解决方案 > Dagger2 注入抽象 ViewModel 的特定实例

问题描述

我有一个 ViewModelFactory 实现如下:

class ViewModelFactory<VM> @Inject constructor(private val viewModel: Lazy<VM>)
: ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
    @Suppress("UNCHECKED_CAST")
        return viewModel.get() as T
    }
}

这适用于我当前的 ViewModel:

class MainActivityViewModel @Inject constructor(private val dependency: Dependency) : ViewModel()
//... in the activity:
@Inject
lateinit var factory: ViewModelFactory<MainActivityViewModel>

private val viewModel: MainActivityViewModel by viewModels { factory }

但是我有不同的构建风格,我想在行为不同的地方实现,所以我创建了一个 AbstractViewModel:

abstract class AbstractViewModel : ViewModel()
//...and so now
class MainActivityViewModel @Inject constructor(private val dependency: Dependency) : AbstractViewModel()
//... and in the activity
@Inject
lateinit var factory: ViewModelFactory<AbstractViewModel>

private val viewModel: AbstractViewModel by viewModels { factory }

我希望能够为 ViewModelFactory 提供特定的实例,但我不确定如何实现这一点。

标签: androiddagger-2android-viewmodel

解决方案


解决了。回答以供将来参考和任何可能有兴趣做类似事情的人。

第 1 步:添加新的模块组件

    @Component(
        modules = [
            //...
            ViewModelModule::class
        ]
    )
    interface ApplicationComponent { //...

这允许开发人员创建一个FlavourApplicationComponent可以替代 的ViewModelModule,我称之为MockViewModelModule

第 2 步:定义模块

    //in the main flavour
    @Module
    class ViewModelModule {
        @Provides
        fun provideMainActivityViewModel(mainActivityViewModel: MainActivityViewModel): AbstractViewModel
        = mainActivityViewModel
    }

    //in the mock flavour
    @Module
    class MockViewModelModule {
        @Provides
        fun provideMainActivityViewModel(mainActivityViewModel: MainActivityViewModel): AbstractViewModel
        = MockMainActivityViewModel()
    }

这实际上可以在运行时进行配置,因此您可以允许用户测试应用程序的所有不同状态,而无需他们进入这些状态。


推荐阅读