Android Library编译后丢失方法,作为AAR依赖时出现方法找不到错误
Compose自定义导航库AAR引入Android端方法不存在问题排查
问题复现场景
开发的Compose跨平台导航库,作为AAR引入Android项目时触发方法不存在异常,直接导入源码则运行正常,报错堆栈如下:
No virtual method setUi(Lkotlin/jvm/functions/Function5;)V in class Lcom/nom/rougthnav/ScreenConfiguration; or its super classes (declaration of 'com.nom.rougthnav.ScreenConfiguration' appears in /data/data/com.nom.myapplication/code_cache/.overlay/base.apk/classes.dex) at com.nom.myapplication.MainActivity$onCreate$1$1$1$router$2$1.invoke(MainActivity.kt:33) at com.nom.myapplication.MainActivity$onCreate$1$1$1$router$2$1.invoke(MainActivity.kt:31) at com.nom.rougthnav.Router.screen(Router.kt:75) at com.nom.rougthnav.Router.screen(Router.kt:47)
涉及的接口定义:
interface RouterScope<K> { fun <T> screen( tag: K, modelFactory: () -> T, block: @Composable (model: T, back: Back, nav: Nav<K>) -> Unit ) var initialTag: K var link: String fun route(tag: K, initial: K, block: RouterScope<K>.() -> Unit) var tagConverter: ((String) -> K)? }
库的build.gradle.kts配置:
plugins { id("org.jetbrains.kotlin.android") id("com.android.library") `maven-publish` } android { compileSdk = 30 defaultConfig { // applicationId = "com.nom.rougthnav" minSdk = 27 targetSdk = 30 // versionCode = 1 // versionName = "1.0" version = "1.6" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } kotlinOptions { jvmTarget = "11" } } dependencies { implementation("androidx.core:core-ktx:1.6.0") implementation("androidx.appcompat:appcompat:1.3.1") implementation("com.google.android.material:material:1.4.0") val compose = "1.0.3" implementation("androidx.compose.ui:ui:$compose") implementation("androidx.compose.ui:ui-tooling-preview:$compose") implementation("androidx.compose.ui:ui-tooling:$compose") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.3") androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") } afterEvaluate { publishing { publications { register("release",MavenPublication::class){ from(components["release"]) groupId = "com.nom.roughtnav" artifactId = "core" version = "${project.version}" } } } }
排查思路
- 首先补全库模块的Compose编译配置,当前android配置块中缺失Compose构建开关和编译器版本指定,添加以下配置:
没有该配置时,库编译阶段不会对android { // 原有配置不变 buildFeatures { compose true } composeOptions { // 版本要和使用的Compose版本、Kotlin版本严格对应,Compose 1.0.3对应kotlinCompilerExtensionVersion为1.0.3,Kotlin版本为1.5.31 kotlinCompilerExtensionVersion = "1.0.3" } }@Composable注解做正确的插桩处理,生成的方法签名和宿主App编译时生成的调用签名不匹配,就会触发方法不存在异常。源码导入时会继承宿主App的编译配置,所以不会出问题。 - 严格对齐库和宿主App的Kotlin版本、Compose编译器版本、Compose依赖版本,三者的版本映射关系是强制绑定的,任意一个版本不匹配都会导致
@Composable函数插桩后的签名不一致。 - 调整Compose相关依赖的声明方式,将
implementation改为api,确保宿主App可以获取到一致的Compose依赖版本,避免间接依赖的版本冲突。 - 用反编译工具(如Jadx)分别查看AAR包中
screen方法的签名,以及宿主App编译后调用该方法的签名,确认两者的参数类型、数量是否一致,可快速定位是否为插桩差异导致的问题。 - 检查maven发布配置是否遗漏了kotlin元数据信息,确保发布的AAR包含完整的kotlin编译元数据,避免宿主App编译时无法识别kotlin特有的函数签名信息。
内容的提问来源于stack exchange,提问作者Basur
相关产品推荐
相关产品推荐

