嗯,有一个叫做GithubBrowser 的,但它不是教程,它是一个项目。你应该知道 dagger for android 来做到这一点。或者,您可以查看以下代码:
@Singleton
class DaggerViewModelFactory @Inject constructor(
private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val creator = creators[modelClass] ?: creators.entries.firstOrNull {
modelClass.isAssignableFrom(it.key)
}?.value ?: throw IllegalArgumentException("unknown model class $modelClass")
try {
@Suppress("UNCHECKED_CAST")
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这部分将为您的整个应用程序创建一个“通用”视图模型。以这种方式,ViewModel创建带有指定参数的 。之后,您需要在单例模块中实现工厂模块,并将其包含在组件中。
@Component(
modules = [... ViewModelModule::class]
)
interface AppCompoenent{}
Run Code Online (Sandbox Code Playgroud)
现在有趣的部分:
@Suppress("unused")
@Module
abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(MyViewModel::class)
abstract fun bindsMyViewModel(viewModel: MyViewModel): ViewModel
@Binds
abstract fun bindsViewModelFactory(factory: DaggerViewModelFactory): ViewModelProvider.Factory
}
Run Code Online (Sandbox Code Playgroud)
由于 Dagger 支持多重绑定,因此您可以随意绑定ViewModels。
视图模型键:
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
Run Code Online (Sandbox Code Playgroud)
您基本上是将值放入哈希图中。这些值是您的ViewModel.
命中构建!完成。之后,您只需ViewModelProvider.Facory在片段中注入一个。比在ViewModel你可以做的:
class MyViewModel @Inject constructor(
private val dependency: YourDependency
) : ViewModel() {}
Run Code Online (Sandbox Code Playgroud)
明确您对评论的要求。首先,没有特别需要知道里面发生了什么DaggerViewModelFactory,虽然我不建议这样学习,因为我是“总是知道发生了什么”的忠实粉丝。仅供参考,这DaggerViewModelFactory只是一个类,它接受Map每个扩展ViewModel为键的类,以及该类的依赖项作为值。使用Provider<T>Dagger 时知道如何找到这些依赖项,但尚未将它们带给您,直到您调用provider.get(). 把它想象成一个懒惰的初始化。
现在检查modelClass.isAssignableFrom(it.key). 它只是检查该类是否真的 extends ViewModel。
至于你的第二个问题,理解第一部分很重要。由于Dagger支持多重绑定,这意味着您可以使用Map<Key, Value>. 例如, aMap<HomeViewModel, Provider<ViewModel>>基本上会告诉 dagger 给我HomeViewModel的依赖项。Dagger 会说:如何知道哪些是HomeViewModel依赖项?你回答:我已经为此定义了一个 Key,它是HomeViewModel类本身。因此,您只需创建一个注释,将其与@Binds和结合@IntoMap,然后在后台 Dagger 将仅执行map.put(HomeViewModel::class, AndDependencies).