欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 游戏 > 一种跨 Activity 的 ViewModel 实现

一种跨 Activity 的 ViewModel 实现

2025/9/23 18:17:33 来源:https://blog.csdn.net/qq_37660755/article/details/143799625  浏览:    关键词:一种跨 Activity 的 ViewModel 实现

背景

阅读该文章之前,我们需要详细了解 ViewModel 的实现原理。类似的文章非常的多,这里不在赘述。

在工作中,我们可能会遇到需要跨 Activity 共享 ViewModel 的场景,比如合集场景的内外流同步。当然了,我们完全可以使用 Fragment 来实现内外流同步这个功能,但由于历史原因,很多老 app 的内流是由 Activity 实现的,改造成 Fragment 已经完全不现实。

我们了解,ViewModel 在设计之时是没有考虑在不同 Activity之间共享的。我们需要使用一些特殊的方法来实现。查询网上大家的实现,发现都各有缺点。如

  1. https://blog.csdn.net/m0_59162559/article/details/138921230 该文章的思路是对的,但它放到了package androidx.lifecycle包下,略显奇怪,或者需要反射去调用store.put 函数。而且没有考虑过内流跳内流场景。(ActivityA->ActivityB->ActivityB)。缺点明显。
  2. https://www.sunofbeach.net/a/1643607587099435009 粗暴的共享 activity 的 viewModelStore,影响面太大。

我们需要实现一个跨 Activity 的ViewModel方案,并没有上述问题。

实现方法

ViewModelStore 是 ViewModel 的容器,是 Acitivty、Fragment 等组件持有 ViewModel 的方式。Activity、Fragment 通过实现 ViewModelStoreOwner 接口,向外界提供自己持有的 ViewModel;在生命周期走到 onDestory 的时候,清空 ViewModelStore,销毁所有数据。

考虑将 ViewModel 的生命周期延长到多个 Activity 生命周期的并集,自然而然的想法是:将同一个 ViewModel 的实例添加到两个 Activity 的 ViewModelStore 中,但是 ViewModelStore 不支持使用者手动调用其put(key: String, viewModel: ViewModel)方法,而且为了更方便的共享多个 ViewModel,我们考虑共享一个特殊的 ViewModelStore,用来承载所有需要共享的 ViewModel。

ACViewModelContainer

该类是一个普通的ViewModel,其内部承载了一个 ViewModelStore,该 ViewModelStore 用与Activity 跳转时候的共享。

class ACViewModelContainer @JvmOverloads constructor(application: Application,viewModelStore: ViewModelStore? = null
): AndroidViewModel(application){companion object {const val UNIVERSAL_SHARE_KEY = "UNIVERSAL_SHARE_KEY"private val refCounter = HashMap<ViewModelStore, Int>()}// 问题的关键在于,我们如何将想要共享的 viewModel 传递到这个 shareViewModelStore 中// 可以知道,在 get 的时候,viewModelProvider 会将创建好的 viewModel 传递到// viewModelStore中,所以,我们需要使用自己的 viewModelProvider 去控制这种行为。val shareViewModelStore = viewModelStore?: ViewModelStore()init {shareViewModelStore.let {refCounter[it] = (refCounter[it]?:0) + 1}}override fun onCleared() {super.onCleared()shareViewModelStore.let {if (!refCounter.containsKey(it) || (refCounter[it]?:0) <= 1) {shareViewModelStore.clear()refCounter.remove(shareViewModelStore)} else {refCounte

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词