如何保存和恢复的Android lambda表达式?(How to save and restore

2019-10-28 13:01发布

当Android的实施状态恢复,我怎么能保存和恢复拉姆达?

我试图将其保存为可序列化和Parcelable,但它抛出一个编译错误。

有没有什么办法来保存和恢复他们,或者我应该寻找其他的办法?

Answer 1:

科特林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是必需的。
  • 在那里你铸造回你的拉姆达类型将抛出一个警告的方法Unchecked cast: Serializable? to YourLambdaType Unchecked cast: Serializable? to YourLambdaType 。 该石膏安全(假设你正确地推断为空!),所以你可以放心地使用剿此警告@Suppress("UNCHECKED_CAST")
  • MyObject必须是SerializableParcelable ,否则它崩溃的运行时间。

现在有没有被告知没有帮助的崩溃日志中运行的任何地方和崩溃细节。 内实现您的拉姆达(即什么是内{ }当你将它)一定不能有到将在以后的时刻被释放对象的引用。 一个典型的例子是:

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

private fun handleLambdaCallback() {
    …
}

这将在运行时崩溃,因为handleLambdaCallback是隐式访问this ,可能会触发尝试递归序列化整个对象图通过它到达,这会在失败时系列化某个时间点。

一个解决这个问题的是送的拉姆达的引用。 例:

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

private fun handleLambdaCallback() {
    …
}

通过这种方式,我们计算的参考,当拉姆达被调用,而不是当它的分配。 绝对不干净的解决方案,但它是我能来最好的,和它的作品。

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



Answer 2:

我应该寻找其他的办法?

是的,有没有一个很好的理由这样做,你的代码不会容易测试,你可能引入内存泄漏。

而不是保存的功能,保存需要要保存的参数(即变量的作用域 ),并调用功能,你通常做。

而不是做

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参数后



文章来源: How to save and restore lambdas in Android?