android - 如何在 Android 中保存和恢复 lambda?

标签 android kotlin state-restoration

在 Android 中实现状态恢复时,如何保存和恢复 lambda?

我尝试将其保存为 Serializable 和 Parcelable,但它会引发编译错误。

有什么方法可以保存和恢复它们,还是我应该寻求其他方法?

最佳答案

Kotlin lambda 实现 Serializable ,所以它们不能像这样保存:

override fun onSaveInstanceState(outState: Bundle) {
    outState.putSerializable("YOUR_TAG", myLambda as Serializable)
    super.onSaveInstanceState(outState)
}

同样,要恢复它们:
override fun onCreate(savedInstanceState: Bundle?) {
    myLambda = savedInstanceState?.getSerializable("YOUR_TAG") as (MyObject) -> Void
    super.onCreate(savedInstanceState)
}

(这显然可以在任何为您提供 savedInstanceState 的生命周期事件中完成,因为这只是一个示例)

一些注意事项:
  • 保存它们时,需要对它们进行强制转换,否则编译器会提示(出于某种原因)。
  • import java.io.Serializable是必须的。
  • 将其转换回 lambda 类型的方法将引发警告 Unchecked cast: Serializable? to YourLambdaType .这个强制转换是安全的(假设你正确地推断出可空性!),所以你可以通过使用 @Suppress("UNCHECKED_CAST") 安全地抑制这个警告。
  • MyObject必须是 SerializableParcelable ,否则它会在运行时崩溃。

  • 现在有一个细节在任何地方都没有被告知,并且在运行时崩溃并且没有有用的崩溃日志。 lambda 的内部实现(即分配它时 { } 中的内容)不能引用稍后将被释放的对象。
    一个经典的例子是:
    // In your MyActivity.kt…
    myLambda = { handleLambdaCallback() } 
    …
    
    private fun handleLambdaCallback() {
        …
    }
    

    这将在运行时崩溃,因为 handleLambdaCallback正在隐式访问 this ,这将触发递归序列化它可访问的整个对象图的尝试,这将在序列化时间的某个时间点失败。

    解决此问题的一种方法是在 lambda 中发送引用。例子:
    // In your MyActivity.kt…
    myLambda = { fragment -> (fragment.activity as MyActivity).handleLambdaCallback() }
    …
    
    private fun handleLambdaCallback() {
        …
    }
    

    这样,我们在调用 lambda 时计算引用,而不是在分配时计算引用。绝对不是最干净的解决方案,但它是我能想到的最好的解决方案,而且它有效。

    随意提出改进和替代解决方案!

    关于android - 如何在 Android 中保存和恢复 lambda?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53939560/

    相关文章:

    android - 如何在Android中获取ObservableField的值

    sorting - 功能快速排序是否有可能比命令快速排序运行得更快?

    ios6 - iOS 6 UIWebView状态还原如何工作?

    ios - 恢复并保留从 UINavigationController 推送的 UIViewController,没有 Storyboard

    android - 缩放和捏合 RelativeLayout

    java - Set<> 为相同的值赋予不同的对象

    java - 软键盘: Adjust_Resize pushing content offscreen

    android - Activity 无法绑定(bind)到服务,完全相同的代码适用于不同的 Activity

    Kotlin - toSet() 与 distinct()

    ios - 应用程序状态保存/恢复