使用 onSaveInstanceState() 和 ViewModel 保存活动的状态
Posted
技术标签:
【中文标题】使用 onSaveInstanceState() 和 ViewModel 保存活动的状态【英文标题】:Saving activity's state with onSaveInstanceState() and ViewModel 【发布时间】:2019-07-17 08:22:18 【问题描述】:阅读本文后,我对 ViewModel 有一些疑问:
https://developer.android.com/topic/libraries/architecture/saving-states
这里说您应该结合使用ViewModel
来进行配置更改(如屏幕旋转),并使用onSaveInstanceState()
来处理活动被销毁然后重新创建以保存 UI 的所有其他情况状态。
我的问题是我们如何知道在调用onCreate(Bundle)
时恢复状态的方式 - 我应该使用 ViewModel 还是应该使用接收到的包作为参数?当配置发生变化时,onSaveInstanceState()
也会被调用,显然onCreate()
总是被调用。
如果我只从 ViewModel 恢复状态,它不会始终保留正确的数据(因为活动可能由于配置更改以外的其他原因而被破坏)。如果我只使用我保存在onSaveInstanceState()
中的捆绑包,那我为什么要使用ViewModel
开头呢?
【问题讨论】:
【参考方案1】:我认为将这些来源视为一个链条很好。 您有 2 个数据源 - ViewModel,速度更快但寿命较短,保存的实例状态较慢但寿命更长。
规则很简单 - 尝试使用您的 ViewModel,如果未填充,请使用来自 onSaveInstanceState() 的包。
当您在 onCreate() 中执行 val model = ViewModelProviders.of(this).get(MyViewModel::class.java)
时,您可以检查是否获得了新的 viewModel 实例。然后,如果它是一个新实例(即它的数据字段为空),您可以从您的包中获取一些基本数据,如内容 ID,并根据该 ID 从后端或数据库中获取数据,用它填充您的新 ViewModel 并然后从 ViewModel 填充您的活动(如果您使用的是 LiveData,这将非常自然)。
下次调用 onCreate 时,您重复该过程,从 ViewModel 填充您的活动,或者使用 Bundle 中的数据填充您的 ViewModel,然后从您的 ViewModel 填充您的活动。
更新: 实际上,官方docs 中描述了非常相似的方法。唯一的区别是您将捆绑包传递给 ViewModel 并由它决定是否需要获取数据,我没有具体说明这种机制。
【讨论】:
如果我在 ViewModel 中拥有的只是初始化为默认值的原语怎么办?我无法判断这是因为该实例是一个新实例,还是这些只是正确的值。无论如何,总的来说,您的建议听起来像是一种解决方法.. 好吧,在这种特殊情况下,您需要实现一些字段来指示您的 ViewModel 不是新创建的,或者将一些数据添加到您的状态包并使用它。如果你只有一堆原语要保存,你不会从使用 ViewModel 中得到太多,在这种情况下,只需实现实例状态并使用它。 ViewModel 可帮助您保留复杂的下载数据或用户生成的数据。 还要检查答案更新,它链接到官方方法。 所以据我了解,它也只是说您应该检查所需的数据是否已经存在.. 是否有某种系统标志告诉您您在 onCreate 中的原因?或者可能是一个标志,告诉您 ViewModel 是否刚刚创建? 我认为当您第一次使用 ViewModelProviders 创建 ViewModel 时,框架不会在 ViewModel 上调用任何参数构造函数,因此您可以将其用作 ViewModel 是新的指标。以上是关于使用 onSaveInstanceState() 和 ViewModel 保存活动的状态的主要内容,如果未能解决你的问题,请参考以下文章
onSaveInstanceState() 和 onRestoreInstanceState()
使用 onSaveInstanceState() 和 ViewModel 保存活动的状态
分离不触发 onSaveInstanceState() 的片段