如何通过 Koin 提供具有接口的 ViewModel

How to provide ViewModel that has interface via Koin

我有以下 ViewModel 设置:

interface FooViewModel {}

class FooViewModelImpl: ViewModel(), FooViewModel {}

我想像这样通过 Koin 提供它:

viewModel<FooViewModel> { FooViewModelImpl() }

它不起作用,因为 Koin 期望在定义中使用 ViewModel 而不是 FooViewModel,并且我不想使我的 FooViewModel 成为从 ViewModel 扩展的抽象 class。

我可以通过 Koin 做到这一点吗?

我让它工作的唯一方法是覆盖 Koin 扩展函数并强制执行限定符:

  • 覆盖 Koin 模块扩展函数以从其泛型定义中删除 ViewModel
inline fun <reified T> Module.customViewModel(
    qualifier: Qualifier? = null,
    noinline definition: Definition<T>
): BeanDefinition<T> {
    return viewModel(qualifier ?: named(T::class.java.name), definition = definition)
}

inline fun <reified T> Module.viewModel(
    qualifier: Qualifier? = null,
    override: Boolean = false,
    noinline definition: Definition<T>
): BeanDefinition<T> {
    val beanDefinition = factory(qualifier, override, definition)
    beanDefinition.setIsViewModel()
    return beanDefinition
}
  • 以相同的方式覆盖 Koin LifecycleOwner 扩展函数:
inline fun <reified T> LifecycleOwner.customViewModel(
    qualifier: Qualifier? = null,
    noinline parameters: ParametersDefinition? = null
): Lazy<T> = lazy { getViewModel<ViewModel>(qualifier ?: named(T::class.java.name), parameters) as T }

inline fun <reified T> LifecycleOwner.getCoreViewModel(
    qualifier: Qualifier? = null,
    noinline parameters: ParametersDefinition? = null
): T = getViewModel<ViewModel>(qualifier ?: named(T::class.java.name), parameters) as T

然后你可以提供 FooViewModel 作为

viewModel<FooViewModel> { FooViewModelImpl() }

并将其注入为:

private val viewModel: FooViewModel by customViewModel()
// or
val viewModel: FooViewModel = getCustomViewModel()

虽然这是可能的,但我认为这不是一个好主意,只是想分享我的发现。最好的方法是使用抽象 class(继承自 Android ViewModel)而不是接口。