如何使用 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
这就是 sharedViewModel
在 koin
中的意思
sharedViewModel
如果您将 ViewModel Factory
与相同的 context
一起使用,则 sharedViewModel
是相同的。
可以通过 Intent
在 Activities
之间共享任何数据,在 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 内部的状态,现在绑定到流程生命周期。
我在 Kotlin 中为 DI 使用 Koin
库
Koin 提供 by viewmodel()
获取 ViewModel by sharedViewModel()
的实例以获取片段中的相同实例。
如何在活动中获得相同的 ViewModel 实例?我没有找到任何方法来实现这一目标。
您需要阅读更多关于 ViewModel
的内容才能更好地理解它。
https://developer.android.com/topic/libraries/architecture/viewmodel
ViewModel
已连接到您的 Activity
所以你只能在他的 Fragments
,
ViewModel
这就是 sharedViewModel
在 koin
sharedViewModel
如果您将 ViewModel Factory
与相同的 context
一起使用,则 sharedViewModel
是相同的。
可以通过 Intent
在 Activities
之间共享任何数据,在 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 内部的状态,现在绑定到流程生命周期。