How to lazily save ViewModel's SavedStateHandle?

大城市里の小女人 提交于 2021-01-27 23:31:03

问题


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.

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().

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().

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


回答1:


This is precisely the use case that the Lifecycle 2.3.0-alpha03 release enables:

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


来源:https://stackoverflow.com/questions/62800028/how-to-lazily-save-viewmodels-savedstatehandle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!