如何懒惰地保存 ViewModel 的 SavedStateHandle? [英] How to lazily save ViewModel's SavedStateHandle?

查看:50
本文介绍了如何懒惰地保存 ViewModel 的 SavedStateHandle?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a screen that loads a bunch of requests and collects some data from the user on the same screen and an external WebView. Therefore, I have a ViewModel that contains these complex request objects (+ user input data). I need to persist this data through system-initiated process death, which SavedStateHandle is designed for. But I don't want to persist this data in a database because it is only relevant to the current user experience.

我已将我的 ViewModel 与 Hilt 集成并收到 SaveStateHandle.因为我有一些复杂的对象在代码的几个地方被访问/修改,所以我无法随时随地"保存它们.我让他们实现 Parcelable 并且只想立即保存它们.不幸的是,ViewModels 没有像 onSaveInstanceState() 这样的生命周期方法.

I have integrated my ViewModels with Hilt and received SaveStateHandle. Because I have some complex objects that are accessed/modified in several places in code I can't save them "on the go". I made them implement Parcelable and just wanted to save them at once. Unfortunately, ViewModels don't have a lifecycle method like onSaveInstanceState().

现在,我尝试使用 onCleared() 这听起来像是写入句柄的好地方.但事实证明,我在那里执行的所有 .set() 操作都会丢失(我正在使用开发人员选项不要保留活动"进行测试.当我使用 .set() 在其他地方,它确实有效).因为 ViewModel 与单个片段/活动的生命周期无关,而是与 NavGraph 相关,所以我无法从它们的 onSaveInstanceState() 中调用.

Now, I have tried using onCleared() which sounded like a ok place to write to the handle. But it turns out that all .set() operations I perform there get lost (I'm testing this with developer options "Don't keep activities". When I use .set() elsewhere, it does work). Because the ViewModel is not tied to the lifecycle of a single fragment/activity but rather to a NavGraph I can't call in from their onSaveInstanceState().

如何/在哪里可以在 SaveStateHandle 中正确保存我的状态?

How/where can I properly persist my state in SaveStateHandle?

推荐答案

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

SavedStateHandle 现在支持延迟序列化,允许您为给定的键调用 setSavedStateProvider(),提供将获得回调的 SavedStateProvidersaveState()SavedStateHandle 被要求保存其状态时.(b/155106862)

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)

这允许您处理任何复杂对象并在需要保存时准确地获得回调.

This allows you to handle any complex object and get a callback exactly when it needs to be saved.

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)
        }
    }
}

这篇关于如何懒惰地保存 ViewModel 的 SavedStateHandle?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆