4

我有一个加载一堆请求的屏幕,并在同一屏幕和一个外部 WebView 上从用户那里收集一些数据。因此,我有一个包含这些复杂请求对象(+ 用户输入数据)的 ViewModel。我需要通过系统启动的进程死亡来保存这些数据,这SavedStateHandle是专为。但我不想将这些数据保存在数据库中,因为它只与当前的用户体验相关。

我已将我的 ViewModel 与 Hilt 集成并收到了SaveStateHandle. 因为我有一些复杂的对象可以在代码中的多个位置访问/修改,所以我无法“随时随地”保存它们。我让它们实现Parcelable,只是想立即保存它们。不幸的是,ViewModel 没有像onSaveInstanceState().

现在,我尝试使用onCleared()听起来不错的地方来写入句柄。但事实证明,.set()我在那里执行的所有操作都会丢失(我正在使用开发人员选项“不要保留活动”进行测试。当我.set()在其他地方使用时,它确实有效)。因为 ViewModel 不绑定到单个片段/活动的生命周期,而是绑定到 NavGraph 我不能从他们的onSaveInstanceState().

我如何/在哪里可以正确地坚持我的状态SaveStateHandle

4

1 回答 1

4

这正是Lifecycle 2.3.0-alpha03 版本启用的用例:

SavedStateHandle现在通过允许您调用setSavedStateProvider()给定的键来支持延迟序列化,提供一个SavedStateProvider将在被要求保存其状态saveState()时获得回调的 a。SavedStateHandle( 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)
        }
    }
}
于 2020-07-08T17:26:46.523 回答