如何在Android中保存和还原Lambda? [英] How to save and restore lambdas in Android?
问题描述
在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
必须为Serializable
或Parcelable
,否则它将在运行时崩溃.
- 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 beSerializable
orParcelable
, 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屋!