NotSerializableException: kotlin.UNINITIALIZED_VALUE 设置 minifyEnabled true 后

NotSerializableException: kotlin.UNINITIALIZED_VALUE after setting minifyEnabled true

在应用 build.gradle 脚本中设置 minifyEnabled true 后,我开始收到此异常:

Caused by: java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = some.package.SomeClass)
    at android.os.Parcel.writeSerializable(Parcel.java:1767)
    …
Caused by: java.io.NotSerializableException: kotlin.UNINITIALIZED_VALUE

当我尝试将 class SomeClass : Parcelable 传递给另一个 activity 时发生崩溃。

我尝试使用 -keep class some.package.**.* { *; } 将所有应用程序 类 列入白名单,但没有成功。

惰性委托在幕后使用 UNINITIALIZED_VALUE 对象。它用于检查变量是否已声明。在某种程度上 [需要更多信息] 惰性委托在代码缩小期间改变了他们的行为。它创建了一种情况,只要 minifyEnabled 被禁用,那么传递带有惰性初始化字段的对象就可以正常工作而无需尝试对其进行序列化。但是在启用 minify 之后 Java 尝试序列化 UNINITIALIZED_VALUE 这会在运行时抛出异常。

不幸的是,stacktrace 不会准确告诉您 class 您必须更新哪个字段。至少它告诉你哪个 main class 包含你损坏的 Serializable class.

假设在这种情况下 some.package.SomeClass 包含 AnotherClass 字段。要修复它,您需要找到 classes 实现 Serializable 的所有惰性 class 字段。然后给他们加上@delegate:Transient,例如

class AnotherClass: Serializable {

    …

    @delegate:Transient // <- add this
    val myLazyField by lazy { "Kotlin, why?!" }
}

我偶然发现了同样的问题,目前的答案是错误的:在惰性上添加 @delegate:Transient 将使反序列化的支持字段无效。

由于问题仅在 minifyEnabled = true 时出现,因此这是一个 Proguard/R8 问题。我通过将以下行添加到我的 proguard-rules.pro:

来解决它
-keep class * implements kotlin.Lazy {
    *;
}