在Android中实现状态恢复时,如何保存和恢复lambda?
我尝试将其保存为Serializable和Parcelable,但是会引发编译错误。
有什么方法可以保存和恢复它们,还是应该寻求其他方法?
答案 0 :(得分:1)
Kotlin lambdas实现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
是必需的。Unchecked cast: Serializable? to YourLambdaType
。此强制转换是安全的(假设您正确推断了可空性!),因此您可以使用@Suppress("UNCHECKED_CAST")
MyObject
必须为Serializable
或Parcelable
,否则它将在运行时崩溃。现在,有一个细节在任何地方都不会告诉您,并且在运行时崩溃,没有有用的崩溃日志。 Lambda的内部实现(即{ }
里面的内容)不能引用稍后将被释放的对象。
一个典型的例子是:
// In your MyActivity.kt…
myLambda = { handleLambdaCallback() }
…
private fun handleLambdaCallback() {
…
}
这将在运行时崩溃,因为handleLambdaCallback
隐式访问this
,这将触发对它可以访问的整个对象图进行递归序列化的尝试,这在序列化过程中有时会失败。 / p>
此问题的一种解决方案是在lambda中发送引用。示例:
// In your MyActivity.kt…
myLambda = { fragment -> (fragment.activity as MyActivity).handleLambdaCallback() }
…
private fun handleLambdaCallback() {
…
}
这样,我们在调用lambda时而不是在分配引用时计算引用。绝对不是最干净的解决方案,但这是我所能提供的最好的解决方案,并且可以使用。
随时提出改进建议和替代解决方案!
答案 1 :(得分:0)
我应该寻求其他方法吗?
是的,没有充分的理由这样做,您的代码将不易于测试,并且可能导致内存泄漏。
而不是保存函数,而是保存需要保存的参数(即 scope 中的变量),然后像平常一样调用函数。
示例
代替做
val name = "John Smith"
val sayHello = { "Hi there, $name" }
startActivity(Intent().apply { putExtra("GREETER", sayHello as Serializable) })
创建可以在其他地方使用的功能
fun sayHello(name: String) = { "Hi there, $name" }
然后稍后使用恢复的name
参数调用