Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。












想改善这个问题吗?更新问题,以便将其作为on-topic用于堆栈溢出。

去年关闭。



Improve this question




如何实现ViewModelFactory以提供我的项目ViewModels及其整个项目的依赖关系?

最佳答案

嗯,有一个叫做GithubBrowser的文件,但这不是教程,而是一个项目。你应该知道 Dagger 为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)
        }
    }
}

这部分将为整个应用程序创建一个“通用” View 模型。以这种方式,创建了ViewModel并分配了参数。之后,您需要在Singleton模块中实现factory模块,并将其包括在组件中。
@Component(
    modules = [... ViewModelModule::class]
)
interface AppCompoenent{}

现在有趣的部分:
    @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
}

由于 Dagger 支持多重绑定(bind),因此您可以根据需要随意绑定(bind)ViewModels

ViewModelKey:
@Target(
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY_GETTER,
    AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)

您基本上是将值放在哈希图中。这些值是您的ViewModel

打建立!完成后,您只需在片段中插入一个ViewModelProvider.Facory。比起您的ViewModel,您可以:
class MyViewModel @Inject constructor(
    private val dependency: YourDependency
) : ViewModel() {}

明确您对评论的要求。首先,虽然我不建议学习这种方式,但我并没有特别的需要知道DaggerViewModelFactory内部发生了什么,因为我是“始终知道正在发生的事情”的坚定拥护者。仅供参考,DaggerViewModelFactory只是一个接受Map的类,每个类都将ViewModel扩展为键,并将该类依赖项作为值。在使用Provider<T>时,Dagger知道如何查找那些依赖项,但是直到您调用provider.get()时,它们才带给您。可以将其视为懒惰的初始化。

现在检查modelClass.isAssignableFrom(it.key)。它只是检查该类是否真的扩展了ViewModel

至于第二个问题,了解第一部分很重要。由于Dagger支持多重绑定(bind),这意味着您可以使用Map<Key, Value>提供依赖项。例如,Map<HomeViewModel, Provider<ViewModel>>基本上会告诉dagger,这给了我HomeViewModel的依赖项。 Dagger 会说:如何知道HomeViewModel的依赖性?您会回答:我已经为此定义了一个键,它是HomeViewModel类本身。因此,您只需创建一个注释,并将其与@Binds@IntoMap结合使用,然后Dagger将在后台执行map.put(HomeViewModel::class, AndDependencies)

09-11 03:07
查看更多