如何在Android中保存和还原Lambda? [英] How to save and restore lambdas in Android?

查看:197
本文介绍了如何在Android中保存和还原Lambda?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

When implementing state restoration in Android, how can I save and restore a lambda?

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

I tried saving it as Serializable and Parcelable, but it throws a compile error.

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

Is there any way to save and restore them, or should I seek other approaches?

推荐答案

Kotlin lambdas实现了Serializable,因此无法像这样保存它们:

Kotlin lambdas implement Serializable, so they can't be saved like:

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的生命周期事件中完成,因为这只是一个示例)

(This can obviously be done in any of the lifecycle events that offer you the savedInstanceState, as this was just an example)

一些注意事项:

  • 保存它们时,必须将其强制转换,否则编译器会抱怨(由于某种原因).
  • import java.io.Serializable是必需的.
  • 将其强制转换回lambda类型的方法将引发警告Unchecked cast: Serializable? to YourLambdaType.此强制转换是安全的(假设您正确推断了可为空性!),因此您可以使用@Suppress("UNCHECKED_CAST")
  • 来安全地禁止此警告.
  • MyObject必须为SerializableParcelable,否则它将在运行时崩溃.
  • When saving them, they need to be casted, otherwise compiler complains (for some reason).
  • import java.io.Serializable is required.
  • The method where you're casting it back to your lambda type will throw a warning Unchecked cast: Serializable? to YourLambdaType. This cast is safe (assuming you infer the nullability correctly!), so you can safely supress this warning by using @Suppress("UNCHECKED_CAST")
  • MyObject must be Serializable or Parcelable, otherwise it crashes in runtime.

现在,有一个细节在任何地方都不会被告知,并且在运行时崩溃,并且没有有用的崩溃日志. Lambda的内部实现(即{ }的内部分配内容)不得引用将在以后释放的对象. 一个典型的例子是:

Now there's a detail that is not told anywhere and crashes in runtime with no helpful crash logs. The inner implementation of your lambda (i.e. what's inside the { } when you assign it) must not have references to objects that will be deallocated in a later moment. A classic example would be:

// In your MyActivity.kt…
myLambda = { handleLambdaCallback() } 
…

private fun handleLambdaCallback() {
    …
}

这将在运行时崩溃,因为handleLambdaCallback隐式访问this,这将触发对它可以访问的整个对象图进行递归序列化的尝试,这在序列化过程中有时会失败.

This will crash in runtime because handleLambdaCallback is implicitly accessing this, which would trigger an attempt to recursively serialize the entire object graph reachable by it, which would fail at some point during serialization time.

此问题的一种解决方案是在lambda中发送引用.示例:

One solution to this problem is to send a reference in the lambda. Example:

// In your MyActivity.kt…
myLambda = { fragment -> (fragment.activity as MyActivity).handleLambdaCallback() }
…

private fun handleLambdaCallback() {
    …
}

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

This way, we are computing the reference when the lambda is invoked, rather than when it's assigned. Definitely not the cleanest solution, but it's the best I could come with, and it works.

请随时提出改进建议和替代解决方案!

Feel free to suggest improvements and alternative solutions!

这篇关于如何在Android中保存和还原Lambda?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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