如何延迟保存 ViewModel 的 SavedStateHandle?
How to lazily save ViewModel's SavedStateHandle?
我有一个屏幕可以加载一堆请求并在同一屏幕和外部 WebView 上收集来自用户的一些数据。因此,我有一个包含这些复杂请求对象(+ 用户输入数据)的 ViewModel。我需要通过系统启动的进程死亡来保留这些数据,SavedStateHandle
就是为此而设计的。但我不想将这些数据持久化到数据库中,因为它只与当前的用户体验相关。
我已将我的 ViewModel 与 Hilt 集成并收到 SaveStateHandle
。因为我在代码的几个地方有一些复杂的对象 accessed/modified,所以我无法“随时随地”保存它们。我让他们实现 Parcelable
并且只想立即保存它们。不幸的是,ViewModel 没有像 onSaveInstanceState()
.
这样的生命周期方法
现在,我尝试使用 onCleared()
,这听起来是一个可以写入句柄的地方。但事实证明,我在那里执行的所有 .set()
操作都丢失了(我正在使用开发人员选项“不保留活动”对此进行测试。当我在其他地方使用 .set()
时,它确实有效)。因为 ViewModel 不依赖于单个 fragment/activity 的生命周期,而是依赖于 NavGraph,所以我无法从它们的 onSaveInstanceState()
.
调用
How/where 我可以在 SaveStateHandle
中正确保留我的状态吗?
这正是 Lifecycle 2.3.0-alpha03 release 启用的用例:
SavedStateHandle
now supports lazy serialization by allowing you to call setSavedStateProvider()
for a given key, providing a SavedStateProvider
that will get a callback to saveState()
when the SavedStateHandle
is asked to save its state. (b/155106862)
这使您可以处理任何复杂的对象并在需要保存时准确地获得回调。
var complexObject: ComplexObject? = null
init {
// When using setSavedStateProvider, the underlying data is
// stored as a Bundle, so to extract any previously saved value,
// we get it out of the Bundle, if one exists
val initialState: Bundle = savedStateHandle.get<Bundle?>("complexObject")
if (initialState != null) {
// Convert the previously saved Bundle to your ComplexObject
// Here, it is a single Parcelable, so we'll just get it out of
// the bundle
complexObject = initialState.getParcelable("parcelable")
}
// Now to register our callback for when to save our object,
// we use setSavedStateProvider()
savedStateHandle.setSavedStateProvider("complexObject") {
// This callback requires that you return a Bundle.
// You can either add your Parcelable directly or
// skip being Parcelable and add the fields to the Bundle directly
// The key is that the logic here needs to match your
// initialState logic above.
Bundle().apply {
putParcelable("parcelable", complexObject)
}
}
}
我有一个屏幕可以加载一堆请求并在同一屏幕和外部 WebView 上收集来自用户的一些数据。因此,我有一个包含这些复杂请求对象(+ 用户输入数据)的 ViewModel。我需要通过系统启动的进程死亡来保留这些数据,SavedStateHandle
就是为此而设计的。但我不想将这些数据持久化到数据库中,因为它只与当前的用户体验相关。
我已将我的 ViewModel 与 Hilt 集成并收到 SaveStateHandle
。因为我在代码的几个地方有一些复杂的对象 accessed/modified,所以我无法“随时随地”保存它们。我让他们实现 Parcelable
并且只想立即保存它们。不幸的是,ViewModel 没有像 onSaveInstanceState()
.
现在,我尝试使用 onCleared()
,这听起来是一个可以写入句柄的地方。但事实证明,我在那里执行的所有 .set()
操作都丢失了(我正在使用开发人员选项“不保留活动”对此进行测试。当我在其他地方使用 .set()
时,它确实有效)。因为 ViewModel 不依赖于单个 fragment/activity 的生命周期,而是依赖于 NavGraph,所以我无法从它们的 onSaveInstanceState()
.
How/where 我可以在 SaveStateHandle
中正确保留我的状态吗?
这正是 Lifecycle 2.3.0-alpha03 release 启用的用例:
SavedStateHandle
now supports lazy serialization by allowing you to callsetSavedStateProvider()
for a given key, providing aSavedStateProvider
that will get a callback tosaveState()
when theSavedStateHandle
is asked to save its state. (b/155106862)
这使您可以处理任何复杂的对象并在需要保存时准确地获得回调。
var complexObject: ComplexObject? = null
init {
// When using setSavedStateProvider, the underlying data is
// stored as a Bundle, so to extract any previously saved value,
// we get it out of the Bundle, if one exists
val initialState: Bundle = savedStateHandle.get<Bundle?>("complexObject")
if (initialState != null) {
// Convert the previously saved Bundle to your ComplexObject
// Here, it is a single Parcelable, so we'll just get it out of
// the bundle
complexObject = initialState.getParcelable("parcelable")
}
// Now to register our callback for when to save our object,
// we use setSavedStateProvider()
savedStateHandle.setSavedStateProvider("complexObject") {
// This callback requires that you return a Bundle.
// You can either add your Parcelable directly or
// skip being Parcelable and add the fields to the Bundle directly
// The key is that the logic here needs to match your
// initialState logic above.
Bundle().apply {
putParcelable("parcelable", complexObject)
}
}
}