使用衍生状态的自定义保存程序rememberSaveable

Bar*_*fet 3 android android-jetpack-compose

我有一个rememberSaveable进行derivedStateOf一些计算以返回一个类作为输出。

我已经将 Parceable/Parcelize 添加到类中,但它仍然崩溃并告诉我实现自定义保护程序。我相信这是因为我正在使用derivedStateOf. 我是否可以保存衍生状态的计算输出的状态?

java.lang.IllegalArgumentException:无法使用当前的 SaveableStateRegistry 保存 DerivedState(value=MyClass(MyClass2()))。默认实现仅支持可以存储在 Bundle 内的类型。请考虑为此类实现自定义 Saver 并将其传递给 RememberSaveable()。

代码看起来像这样

val someCalculation by rememberSaveable(someTriggering) {
        derivedStateOf {
            someCalculationThatReturnsAClass()
        }
    }
Run Code Online (Sandbox Code Playgroud)

小智 6

您没有将自定义保护程序传递给您的rememberSaveable().

您感兴趣的 RememberSaveable 参数是:

  • 输入 - 一组输入,当其中任何一个发生更改时,将导致状态重置并重新运行 init
  • saver - Saver 对象,定义如何保存和恢复状态

您只需将 someTriggering 作为输入传递。

代码可能如下所示:

val someCalculation by rememberSaveable(
   inputs = someTriggering,
   saver = YourCustomSaver
) {
    derivedStateOf {
        someCalculationThatReturnsAClass()
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处了解如何创建自定义保护程序:保护程序文档

import androidx.compose.runtime.saveable.Saver

data class Holder(var value: Int)

// this Saver implementation converts Holder object which we don't know how to save
// to Int which we can save
val HolderSaver = Saver<Holder, Int>(
    save = { it.value },
    restore = { Holder(it) }
)
Run Code Online (Sandbox Code Playgroud)

以及如何使用它:rememberSaveable 文档

import androidx.compose.runtime.saveable.rememberSaveable

val holder = rememberSaveable(saver = HolderSaver) { Holder(0) }
Run Code Online (Sandbox Code Playgroud)

我是否可以保存衍生状态的计算输出的状态?

是的,Google 在其Compose 性能中提供了一个使用该方法的示例,即使用 returnedStateOf段落。

这是他们添加的代码片段:

val listState = rememberLazyListState()
LazyColumn(state = listState) {
  // ...
  }

val showButton by remember {
    derivedStateOf {
        listState.firstVisibleItemIndex > 0
    }
}

AnimatedVisibility(visible = showButton) {
    ScrollToTopButton()
}
Run Code Online (Sandbox Code Playgroud)