如何为活动使用ViewModel单例?

5

我的应用程序需要在整个上下文中保存一个用户对象,A、B、C活动的xml使用此用户对象。当A编辑用户时,我希望B和C被通知到变化。如何使用databinding、livedata和viewModel解决这个问题?

以前,我让User.class扩展BaseObservable,但POJO会很麻烦而且不能为null,有时候User可能为null,比如未登录。现在我改用LiveData,使POJO简单且不继承BaseObservable,但当A编辑时,B和C不起作用,我认为我需要ABC在内存中使用相同的viewModel实例,但这将导致viewModel的onClear()触发多次。


您可以定制 ViewModelFactory 以使用单例 ViewModel。 - Jeel Vankhede
这并不像这篇博客文章所暗示的那样糟糕,但是ViewModel确实有一些陷阱需要注意。你的问题很难理解,但听起来你可能已经掉进了其中一个陷阱。 - StackOverthrow
@Jeel Vankhede,我在https://github.com/googlesamples/android-architecture-components/issues/29#issuecomment-407291032中找到了ViewModelFactory的解决方案,但是viewModel的onCleared()可能会触发三次或更多。 - candrwow
3个回答

5
另一种方法是拥有一个单例仓库来保存用户数据,每个viewModel都可以拥有该仓库,并在不同的活动之间共享相同的数据。

3

根据这份文档的介绍:https://developer.android.com/topic/libraries/architecture/livedata#extend_livedata

LiveData对象具有生命周期感知功能,这意味着您可以在多个Activity、Fragment和Service之间共享它们。为了让示例保持简单,可以按以下方式实现LiveData类的singleton模式:

您可以像这里一样为您的ViewModel创建一个singleton模式:

    companion object{
        private lateinit var instance: ViewModelProfile
        
        @MainThread
        fun getInstance(userId: String): ViewModelProfile{
            instance = if(::instance.isInitialized) instance else ViewModelProfile(userId)
            return instance
        }
    }

那么我可以随时调用它来获取实例:

    val profileVModel = ViewModelProfile.getInstance(user.uid)

1
如果您想在ABC活动之间共享公共的ViewModel,建议将它们保留为单个Activity中的3个片段,并创建该Activity的ViewModel,可在A、B和C三个片段之间共享。

此外,如果您要在活动A中执行某些操作,并希望活动B和C得到通知,则它们需要正在运行才能得到通知,这是不可能的。因此,您应该使用IntentBundle在活动启动时传递所需的信息。

更新

还有其他方法可以实现类似的功能,例如:

  • 事件总线
  • RxJava主题(参见this
  • Evernote的Android State(参见this

这将允许您具有应用程序级别的状态访问权限,可由任何活动或片段访问。


Android State by Evernote 不再维护。 - wesley franks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接