如何使用 Koin DI 在活动之间共享相同的 ViewModel 实例?

How to share same instance of ViewModel between Activities using Koin DI?

我在 Kotlin 中为 DI 使用 Koin

Koin 提供 by viewmodel() 获取 ViewModel by sharedViewModel() 的实例以获取片段中的相同实例。

如何在活动中获得相同的 ViewModel 实例?我没有找到任何方法来实现这一目标。

您需要阅读更多关于 ViewModel 的内容才能更好地理解它。 https://developer.android.com/topic/libraries/architecture/viewmodel

ViewModel 已连接到您的 Activity

所以你只能在他的 Fragments ,

之间分享你的活动 ViewModel

这就是 sharedViewModelkoin

中的意思

sharedViewModel 如果您将 ViewModel Factory 与相同的 context 一起使用,则 sharedViewModel 是相同的。

可以通过 IntentActivities 之间共享任何数据,在 Android、

中没有其他方法

或者您可以保留一些 static / global 数据并在 Activities

之间共享

在对架构级别进行一些研究或讨论并报告和发布 github Koin 之后,我找到了解决方案 在这种情况下,我们应该将 state/data 保存到存储库中,我们需要在不在 viewModel 中的多个活动之间共享,并且两个或多个不同的 ViewModel 可以访问保存在单个存储库实例中的相同 state/data

您必须在模块声明中使用 single{} 而不是 viewModel{}

single { SharedViewModel() }

而且,您可以在视图中使用 viewModel()。

视图 1

private val viewModel: SharedViewModel by viewModel()

视图 2

private val viewModel: SharedViewModel by viewModel()

但是你必须在视图启动时加载模块

loadKoinModules(module1)

重点是销毁视图时必须卸载模块

unloadKoinModules(mainModule)

因此,当卸载模块时,您的单例 ViewModel 将被销毁。

#编辑

现在,您可以使用 sharedViewModel 声明。

我建议将应用设为 ViewModelStoreOwner 并以应用所有者身份注入 viewModel。 所需的代码如下所示

class App : Application(), ViewModelStoreOwner {
    private val mViewModelStore = ViewModelStore()

    override fun getViewModelStore(): ViewModelStore {
        return mViewModelStore
    }
}

您可以定义一些扩展来轻松注入 viewModels


val Context.app: App
    get() = applicationContext as App

inline fun <reified T : ViewModel> Context.appViewModel(
    qualifier: Qualifier? = null,
    noinline state: BundleDefinition? = null,
    noinline parameters: ParametersDefinition? = null
): Lazy<T> {
    return lazy(LazyThreadSafetyMode.NONE) {
        GlobalContext.get().getViewModel(qualifier, state, { ViewModelOwner.from(app, null) }, T::class, parameters)
    }
}

inline fun <reified T : ViewModel> Fragment.appViewModel(
    qualifier: Qualifier? = null,
    noinline state: BundleDefinition? = null,
    noinline parameters: ParametersDefinition? = null
): Lazy<T> {
    return lazy(LazyThreadSafetyMode.NONE) {
        GlobalContext.get().getViewModel(qualifier, state, { ViewModelOwner.from(requireContext().app, null) }, T::class, parameters)
    }
}

然后您可以像这样注入您的 viewModel

class MainActivity : AppCompatActivity() {
    private val mAppViewModel: AppViewModel by appViewModel()
}

此解决方案的优点是您不需要重新创建视图模型,如果您决定在应用重新启动之间保存状态,您也可以轻松地使应用成为 SavedStateRegistryOwner 并使用SavedStateHandle save/restore 您在 viewModel 内部的状态,现在绑定到流程生命周期。