NotSerializableException:将minifyEnabled设置为true后,kotlin.UNINITIALIZED_VALUE

时间:2020-08-20 12:50:59

标签: android kotlin gradle delegates serializable

在应用minifyEnabled true脚本中设置了build.gradle之后,我开始注视着这个异常:

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传递给另一个活动时发生崩溃。

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

2 个答案:

答案 0 :(得分:1)

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

由于仅在minifyEnabled = true时才发生此问题,所以这是Proguard / R8问题。我通过在我的proguard-rules.pro中添加以下几行来解决该问题:

-keep class * implements kotlin.Lazy {
    *;
}

答案 1 :(得分:0)

惰性委托在后台使用UNINITIALIZED_VALUE对象。用于检查变量是否已声明。以某种方式[需要更多信息]懒惰的委托在代码最小化期间​​更改其行为。它会造成这样的情况,只要禁用minifyEnabled,然后传递带有惰性初始化字段的对象就可以正常工作而无需尝试对其进行序列化。但是启用minify后,Java会尝试将可序列化的UNINITIALIZED_VALUE序列化,从而在运行时引发异常。

不幸的是,stacktrace不能准确地告诉您必须更新哪个类中的哪个字段。至少它告诉您哪个主类包含损坏的Serializable类。

让我们假设在这种情况下some.package.SomeClass包含AnotherClass字段。要解决此问题,您需要找到所有实现类Serializable的惰性类字段。然后向其中添加@delegate:Transient,例如。

class AnotherClass: Serializable {

    …

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