Android多模块依赖同一库不同版本及Shadow插件Compose函数导入故障
问题背景
我们在:app模块中将androidx.compose.foundation:foundation从1.4.3升级到1.6.2以获取新特性,但独立feature模块中使用androidx.compose.foundation.pager的功能出现崩溃。由于暂无重构资源,希望保留该模块中foundation的1.4.3版本:
- 直接声明
implementation("androidx.compose.foundation:foundation:1.4.3")会触发类签名冲突,Gradle默认采用app模块的1.6.2版本 - 尝试通过Gradle Shadow插件将1.4.3版本重命名为
com.xxx.legacy.androidx.compose.foundation后,可导入类(如PagerState),但无法导入Compose函数(如HorizontalPager,提示Unresolved reference)
相关配置如下:
Feature模块build.gradle.kts
plugins { id("com.android.library") id("org.jetbrains.kotlin.android") } apply<ShadowAarDependenciesPlugin>() android { // ... compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = compose_version } kotlinOptions { jvmTarget = "17" } packaging { resources { merges += "META-INF/*.kotlin_module" excludes += "META-INF/*.version" } } } extensions.getByType(ShadowAarDependenciesPluginExtension::class.java).apply { relocations.set(mutableListOf( listOf("androidx.compose.foundation", "com.xxx.legacy.androidx.compose.foundation"), )) } dependencies { implementation(platform("androidx.compose:compose-bom:2023.10.01")) add("aarImplementation", "androidx.compose.foundation:foundation:1.4.3") implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-util") implementation("androidx.compose.material3:material3") }
buildSrc的build.gradle.kts
plugins { `kotlin-dsl` } repositories { gradlePluginPortal() } dependencies { implementation("com.github.johnrengelman:shadow:8.1.1") }
问题原因
- Compose顶层函数元数据未被处理:
HorizontalPager是Kotlin顶层函数,其引用元数据存储在META-INF/*.kotlin_module文件中。Shadow插件默认仅重编译字节码中的包路径,未更新这些元数据里的函数归属包名,导致Compose编译器无法定位重命名后的函数。 - ShadowAarDependenciesPlugin对Compose支持不足:该插件未覆盖Compose特有的合成代码(如顶层函数生成的
HorizontalPagerKt辅助类),这些合成类的包名未被重命名,进一步导致引用失效。 - Compose BOM版本约束干扰:引入的
compose-bom:2023.10.01会强制统一所有Compose库版本,可能导致aarImplementation声明的1.4.3版本被覆盖,实际参与构建的仍是1.6.2版本。
解决方案
方案1:完善Shadow插件配置,处理Kotlin元数据
修改feature模块的build.gradle.kts,添加自定义Transformer处理kotlin_module元数据文件,并排除BOM对foundation的版本约束:
plugins { id("com.android.library") id("org.jetbrains.kotlin.android") } apply<ShadowAarDependenciesPlugin>() android { // 保持原有配置不变 } extensions.getByType(ShadowAarDependenciesPluginExtension::class.java).apply { relocations.set(mutableListOf( listOf("androidx.compose.foundation", "com.xxx.legacy.androidx.compose.foundation"), )) // 添加自定义Transformer处理Kotlin元数据 transformers.add(object : com.github.jengelman.gradle.plugins.shadow.transformers.Transformer { override fun canTransformResource(resourcePath: String): Boolean { return resourcePath.startsWith("META-INF/") && resourcePath.endsWith(".kotlin_module") } override fun transform(context: com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext) { val content = context.inputStream.bufferedReader().readText() val modifiedContent = content.replace("androidx.compose.foundation", "com.xxx.legacy.androidx.compose.foundation") context.outputStream.write(modifiedContent.toByteArray()) } }) } dependencies { // 排除BOM对foundation的版本约束 implementation(platform("androidx.compose:compose-bom:2023.10.01")) { exclude(group = "androidx.compose.foundation") } add("aarImplementation", "androidx.compose.foundation:foundation:1.4.3") implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-util") implementation("androidx.compose.material3:material3") }
方案2:用Gradle依赖解析强制指定版本
放弃Shadow插件,直接在feature模块中强制使用foundation 1.4.3版本,同时处理BOM的版本约束:
android { // 保持原有配置不变 } // 强制feature模块使用foundation 1.4.3 configurations.all { resolutionStrategy { force("androidx.compose.foundation:foundation:1.4.3") force("androidx.compose.foundation:foundation-layout:1.4.3") // 关联库也需强制版本 } } dependencies { // 移除BOM对foundation的约束,或手动指定其他Compose库版本 implementation(platform("androidx.compose:compose-bom:2023.10.01")) { exclude(group = "androidx.compose.foundation") } implementation("androidx.compose.foundation:foundation:1.4.3") implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-util") implementation("androidx.compose.material3:material3") }
注意:此方案需确保app模块与feature模块之间没有共享依赖foundation的组件,避免运行时类加载冲突。
方案3:隔离Pager功能到独立模块
将使用1.4.3 Pager的代码提取到独立库模块,彻底隔离版本:
- 新建
:pager-legacy模块,build.gradle.kts配置:
plugins { id("com.android.library") id("org.jetbrains.kotlin.android") } android { compileSdk = 34 defaultConfig { minSdk = 24 } buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = "1.4.3" // 与foundation 1.4.3匹配 } } dependencies { implementation("androidx.compose.foundation:foundation:1.4.3") implementation("androidx.compose.ui:ui:1.4.3") }
- 将feature模块中
HorizontalPager相关代码迁移到:pager-legacy,暴露必要API - 在feature模块中依赖
:pager-legacy,同时正常使用1.6.2版本的其他Compose库
关键注意事项
- Compose编译器版本必须与foundation版本匹配:foundation 1.4.3对应compose compiler 1.4.3,1.6.2对应compiler 1.5.3,多版本共存时需确保各模块的compiler版本正确。
- Shadow插件对Compose的支持存在局限性,自定义Transformer是补充处理的核心。
内容的提问来源于stack exchange,提问作者Calamity
相关产品推荐
相关产品推荐

