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

Nij*_*dli 7 android interface viewmodel koin

我有以下 ViewModel 设置:

interface FooViewModel {}

class FooViewModelImpl: ViewModel(), FooViewModel {}
Run Code Online (Sandbox Code Playgroud)

我想通过 Koin 提供它,如下所示:

viewModel<FooViewModel> { FooViewModelImpl() }
Run Code Online (Sandbox Code Playgroud)

它不起作用,因为 Koin 在定义中需要 ViewModel 而不是 FooViewModel,而且我不想让我的 FooViewModel 成为从 ViewModel 扩展的抽象类。

有什么办法可以通过 Koin 做到这一点吗?

Nij*_*dli 2

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

  • ViewModel重写 Koin 模块扩展函数以从其泛型定义中删除:
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
}
Run Code Online (Sandbox Code Playgroud)
  • 以相同方式覆盖 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
Run Code Online (Sandbox Code Playgroud)

然后你可以提供 FooViewModel 作为

viewModel<FooViewModel> { FooViewModelImpl() }
Run Code Online (Sandbox Code Playgroud)

并将其注入为:

private val viewModel: FooViewModel by customViewModel()
// or
val viewModel: FooViewModel = getCustomViewModel()
Run Code Online (Sandbox Code Playgroud)

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