启用R8的Release构建中Typesafe Navigation序列化INSTANCE缺失问题
问题分析与解决方案
根本原因
R8在Release构建的代码收缩优化过程中,会移除它判定为无直接引用的类成员。对于嵌套的@Serializable data object(如OwnerGraph.HistoryGraph):
- 它作为导航图的泛型参数被使用,而Java/Kotlin的泛型会在编译时发生类型擦除,R8的静态分析无法识别到它被kotlinx.serialization的反射机制间接引用;
- 最终R8会删除该object的
INSTANCE静态字段,同时移除kotlinx.serialization插件为其生成的序列化器元数据,导致运行时找不到对应序列化器,抛出异常。
解决方案
1. 显式引用序列化器(推荐)
在导航图配置代码中,显式调用目标类的serializer()方法,让R8明确感知到该类被使用:
fun NavGraphBuilder.historyScreenOwnerNavGraph() { // 显式引用序列化器,阻止R8优化移除 val _ = OwnerGraph.HistoryGraph.serializer() val _ = OwnerGraph.HistoryGraph.HistoryScreen.serializer() navigation<OwnerGraph.HistoryGraph>( startDestination = OwnerGraph.HistoryGraph.HistoryScreen ) { composable<OwnerGraph.HistoryGraph.HistoryScreen> { navBackStackEntry -> val navHostController = LocalNavHostController.current Text("History Screen") } } }
2. 添加@Keep注解(快速修复)
直接给被优化移除的data object添加@Keep注解,强制R8保留该类的所有成员和元数据:
@Serializable data object OwnerGraph { @Keep @Serializable data object HistoryGraph { @Serializable data object HistoryScreen } }
3. 配置全局R8规则(批量处理)
如果项目中有多个类似的嵌套序列化object,可在proguard-rules.pro中添加全局规则,自动保留所有@Serializable标识的object类及其序列化相关内容:
# 保留@Serializable注解的类名 -keepnames class @kotlinx.serialization.Serializable * # 保留所有序列化器的INSTANCE字段 -keepclassmembers class ** implements kotlinx.serialization.KSerializer { public static ** INSTANCE; } # 保留@Serializable标识的object类的INSTANCE字段 -keepclassmembers @kotlinx.serialization.Serializable class ** { public static final ** INSTANCE; }
内容的提问来源于stack exchange,提问作者No_Name
相关产品推荐
相关产品推荐

