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
, иначе оно вылетает во время выполнения.
Теперь есть деталь, которая нигде не сообщается и падает во время выполнения без полезных журналов аварий.Внутренняя реализация вашей лямбды (т.е. то, что находится внутри { }
, когда вы ее назначаете) не должна иметь ссылок на объекты, которые будут освобождены в более поздний момент.Классическим примером будет:
// 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() {
…
}
Таким образом, мы вычисляем ссылку, когда вызывается лямбда, а не когда она назначена.Определенно, это не самое чистое решение, но это лучшее, что я могу предложить, и оно работает.
Не стесняйтесь предлагать улучшения и альтернативные решения!