Android不同AAR存在同名类与布局引发ClassCastException问题咨询
问题根因
Android资源合并机制规定:当多个依赖库存在同名资源时,最终打包进APK的是优先级更高的依赖对应的资源版本。你遇到的异常是因为
module_B的资源优先级高于module_A,导致module_A代码中引用的R.layout.search_result实际加载的是module_B的布局,该布局中声明的是com.module_B.XTextView,因此强转为com.module_A.XTextView时触发类型转换异常。
解决方案(无需修改AAR内容)
方案1:调整依赖声明顺序(改造成本最低)
Android Gradle 插件的资源合并优先级与依赖声明顺序正相关,越靠后声明的依赖,资源优先级越高,高优先级的同名资源会覆盖低优先级资源。
你只需要修改主模块build.gradle中的依赖顺序,将module_A的声明放在module_B之后即可,最终APK中保留的search_result.xml就会是module_A的版本:
// 调整前(优先级 module_B > module_A) // implementation(name: 'module_A', ext: 'aar') // implementation(name: 'module_B', ext: 'aar') // 调整后(优先级 module_A > module_B) implementation(name: 'module_B', ext: 'aar') implementation(name: 'module_A', ext: 'aar')
注意:该方案会导致所有同名资源都以module_A的版本为准,如果你的项目需要同时使用两个模块的同名资源,请选择方案2
方案2:通过模块专属上下文加载对应资源
通过反射获取指定模块的资源ID,并用对应模块的上下文加载布局,可以完全规避资源覆盖问题,同时支持两个模块的同名资源独立使用:
修改AResultAdapter的onCreateViewHolder逻辑如下:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ResultItemHolder { // 获取module_A专属上下文 val moduleAPkg = "com.module_A" val moduleAContext = parent.context.createPackageContext( moduleAPkg, Context.CONTEXT_IGNORE_SECURITY or Context.CONTEXT_INCLUDE_CODE ) // 反射获取module_A内部的search_result布局ID val layoutId = moduleAContext.resources.getIdentifier("search_result", "layout", moduleAPkg) // 用module_A的布局加载器加载布局 val view = LayoutInflater.from(moduleAContext).inflate(layoutId, parent, false) return ResultItemHolder(view) }
注意:使用时需要捕获PackageManager.NameNotFoundException等异常,避免模块未正常引入时崩溃
内容的提问来源于stack exchange,提问作者Cheng
相关产品推荐
相关产品推荐

