谷歌前段时间废弃了 startActicityForResult
取而代之的是 ActicityResultApi
,作为一个紧跟谷歌步伐走的菜鸟开发者,当然想着的是第一时间学习并替换项目中的相关代码。
但是,奇怪的是,IDE 没有警告 startActicityForResult
已废弃,只是在编译时会警告该方法已废弃。
虽然不知道为什么,但是我还是自己手动找到了所有使用了 startActicityForResult
的地方,并且更改为 ActicityResultApi
。
然而,IDE 却爆红了,提示 Unresolved reference: registerForActivityResult
。
我一开始怀疑是我写错了,但是我尝试着编译运行了一下,却没有出错,也能够正常运行。
作为一名面向搜索引擎编程的菜鸡,想到的第一件事当然是先谷歌一下看看咯。
在 stackoverflow 上,大多数人指出出现这个问题是因为 AndroidX 的 activity 依赖版本过低,尚不支持该方法,但是我很确信我的依赖版本已经是最新版本了。
接着往下搜索,发现了有人说可以通过强制转换类型来解决:
private val requestPermission = (this as ComponentActivity).registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
}
显然,这样只是治标不治本。所以继续搜索。
在谷歌的 issuetracker 上找到两条这样的 issue:
Superclass resolution fails with 2 versions of the library in the project
、Bug: unable to find registerForActivityResult on large project despite having the needed dependencies
上面的 issue 大致是说,如果依赖同一个库有不同的版本,那么 IDE 可能会解析到错误的库版本,导致某些新版本中的 API 无法被 IDE 解析到。
总而言之,这是 IDEA 的一个 BUG 被 Android Studio “继承” 了过来。
那么,这个问题就无法解决,只能等官方修复了吗?
非也,既然知道了导致 BUG 的原因,我们当然是要去避免触发这个 BUG 了。
首先查看一下项目依赖:
很显然可以看到,项目确实同时依赖了两个 acticity 库,其中一个为 1.0.0 版本(无 ActicityResultApi),另外一个为 1.5.0 版本(有 ActicityResultApi),而我很确信,我在主模块(app)中依赖的是 1.5.0 版本,但是 IDE 解析时却解析的是 1.0.0 版本。
找到了问题确实存在,下一步则是找出是哪个模块或者哪个第三方库引用了 1.0.0 版本的 acticity。
依次点击 Adnroid Stuidio 的菜单 File - Project Structure - Dependencies
打开依赖树分析窗口。
然后在 All Modules 中 选中 activity:1.0.0 查看依赖路径:
从依赖路径中能明显看到,1.0.0 版本的 activity 是被 imageEdit 模块的 appcompat 依赖引入的。
我们看一下 iamgeEdit 模块的 build.gradle 模块:
dependencies {
......
implementation 'androidx.appcompat:appcompat:1.1.0'
......
}
确实发现该模块依赖了 appcompat 库。
注:我之所以言之凿凿的说 activity 是被 appcompat 引入的而非如图中所示的第一级依赖明明是 fragment ,是因为 fragment 其实也是被 appcompat 引入,因为这两个库是相互依赖的关系。并且我的依赖中也只写了 appcompat ,并未添加 fragment ,所以才得出如上结论。
知道了诱发错误的原因后,更改起来就很简单了,只需要把 iamgeEdit 模块的 appcompat 库等级改为最新版本或支持 ActicityResultApi 的适合自己项目的版本即可。
这里我将 appcompat 更新到最新版本后可以看到错误已消失:
虽然问题已经解决了,但是我们不应该止步于见招拆招,而应该有更多的思考:为什么会出现依赖冲突?
由于这个项目最开始是单模块项目,后来越写越大,才逐渐拆分出其他子模块,所以压根没有做依赖管理。
一个健康的项目,应该有一个统一的依赖管理,而不是随心所欲的各个模块胡乱添加依赖。
在此推荐大佬写的文章:
【Gradle7.0】依赖统一管理的全新方式,了解一下~
文章中也有其他依赖管理方式的链接,大伙可以根据自己的项目需求自行选择。
该文章首发于我的博客:likehide.com