我已经开始使用匕首2了,所以还有很多东西要学。我想知道是否有人能给我指出正确的方向。
因此,我创建了一个模块,用于注册活动使用的视图模型。看起来是这样的:
@Module
abstract class ViewModelModule {
@Binds
internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(MainActivityViewModel::class)
internal abstract fun bindMainActivityViewModel(viewModel: MainActivityViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(ShowDetailsViewModel::class)
abstract fun bindShowDetaislViewModel(viewModel: ShowDetailsViewModel): ViewModel
}
ViewModelKey
是一个简单的助手注释类,如下所示:
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey (val value: KClass<out ViewModel>) {
}
这个
ViewModelModule
@Singleton
@Component(
modules=[
AndroidSupportInjectionModule::class,
AppModule::class,
DatabaseModule::class,
NewsServiceModule::class,
JobBindingModule::class,
ViewModelModule::class,
PreferencesModule::class,
ActivityBindingModule::class
]
)
interface AppComponent: AndroidInjector<MyApp> {
@Component.Builder
abstract class Builder: AndroidInjector.Builder<MyApp>()
}
这是密码
ActivityBindingModule
@Module
abstract class ActivityBindingModule {
@ActivityScoped
@ContributesAndroidInjector()
internal abstract fun mainActivity(): MainActivity
@ActivityScoped
@ContributesAndroidInjector
internal abstract fun showDetailsActivity(): ShowDetailsActivity
}
在内部,每个活动都用如下代码实例化视图模型(在
onCreate
//view model code
_viewModel = ViewModelProviders.of(this, viewModelFactory)[ShowDetailsViewModel::class.java]
如你所料,
viewModelFactory
作为字段注入:
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
为了完整起见,下面是我的视图模型工厂的代码:
@Singleton
class ViewModelFactory @Inject constructor(private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T
= viewModels[modelClass]?.get() as T
这段代码可以工作,但似乎可以改进。看完文档后,我觉得我可以重构我的
ViewModeModule
这样它就可以简单地实例化我的
ViewModelFactory
为了测试这个,我从移动
ShowDetailsViewModel
新模块只有一个条目:
@Module
internal abstract class DetailsModule {
@Binds
@IntoMap
@ViewModelKey(ShowDetailsViewModel::class)
abstract fun bindShowDetaislViewModel(viewModel: ShowDetailsViewModel): ViewModel
}
@Module
abstract class ViewModelModule {
@Binds
internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(MainActivityViewModel::class)
internal abstract fun bindMainActivityViewModel(viewModel: MainActivityViewModel): ViewModel
}
我已经更新了
所以看起来像这样:
@Module
abstract class ActivityBindingModule {
@ActivityScoped
@ContributesAndroidInjector()
internal abstract fun mainActivity(): MainActivity
@ActivityScoped
@ContributesAndroidInjector(modules = [DetailsModule::class])
internal abstract fun showDetailsActivity(): ShowDetailsActivity
}
DetailsModule
(它实例化
)到
ContributeAndroidInjector
应用于
showDetailsActivity
现在,我肯定错过了一些东西,因为这样做后,我总是得到以下例外:
java.lang.IllegalStateException: ViewModelProviders.of(thâ¦ilsViewModel::class.java] must not be null
MainActivityViewModel
我认为,将每个视图模型和声明移动到子组件使用的每个a模块中,仍然应该允许它注册到由向顶部组件注册的模块注入的映射中。我错了吗?是什么让我错过了这项工作?
谢谢。