Android Navigation Component release变体下Parcelable参数找不到问题
问题原因
你遇到的是R8/ProGuard混淆裁剪导致的类丢失问题:
- Debug模式默认关闭混淆、无用类裁剪功能,所以类能正常加载运行
- Release模式开启R8优化后,Navigation Component解析自定义Parcelable类型的导航参数时,是通过反射调用
Class.forName()加载目标类,R8无法识别到这种隐式的类引用,会误将你的Article类判定为无用类裁剪,同时也可能混淆类的全限定名,最终导致反射找不到类抛出异常 - 模型类放在独立模块的场景下,独立模块如果没有单独配置混淆规则,被主模块的混淆规则裁剪的概率会更高
解决方案
1. 给独立模型模块添加混淆规则
在独立模型模块的proguard-rules.pro文件中添加如下规则:
# 保留所有Parcelable实现类和Creator字段 -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } # 替换成你自己的模型类所在的包路径,保留包下所有类不被混淆裁剪 -keep class com.xxx.app_models.** { *; } # 保留@Parcelize注解标记的类 -keep @kotlinx.parcelize.Parcelize class * { *; } # 如果用到kotlinx-serialization,添加下方规则避免序列化异常 -keepattributes *Annotation*, InnerClasses -keepclassmembers class kotlinx.serialization.json.** { *** Companion; } -keepclasseswithmembers class * { kotlinx.serialization.KSerializer serializer(...); }
2. 独立模块开启混淆配置
在独立模型模块的build.gradle(Groovy)或build.gradle.kts(Kotlin DSL)中关联你刚才添加的混淆规则:
Groovy 配置示例
android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } }
Kotlin DSL 配置示例
android { buildTypes { release { isMinifyEnabled = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) } } }
3. 可选优化
升级Navigation Component到2.5.0及以上版本,新版对自定义Parcelable类型参数的加载逻辑做了优化,可降低反射和混淆的冲突概率。
4. 验证生效
打包Release APK后,通过Android Studio顶部菜单栏 Build -> Analyze APK 打开生成的APK,查看dex文件中是否存在Article类,类的全限定名是否和代码中一致即可验证规则是否生效。
内容的提问来源于stack exchange,提问作者Badr At
相关产品推荐
相关产品推荐

