今天导入一个第三方库的时候,发现里面的 okhttp 冲突了,找了很多文字都不顶用,最后发现菜狗原来是我自己,我把引入时剔除那个 groovy 写法掉了个逗号,真是笑掉大牙!
下面做一番总结吧!
解决办法
问题原因就是,各个模块所有的依赖(递归)的 jar 包最后都会加载到安卓的项目中,你可以选择 project 形式查看 External Libraries,都在这了。所以解决问题关键就是干掉冲突,剩下一个就行了,或者全不要就行了!
下面直接先上解决办法吧,急性子就不为难急性子了,本人最烦的就是说一大堆废话,后面几行代码就能问题。
1、引入时剔除
//逗号别掉了 implementation 'com.ezviz.sdk:ezuikit:2.2.1', { exclude group: 'com.squareup.okhttp3', module: 'okhttp' } //或者用下面方式 // implementation('com.ezviz.sdk:ezuikit:2.2.1') { // exclude group: 'com.squareup.okhttp3', module: 'okhttp' // }
这里直接拿我解决的 SDK 为例,其中 okhttp 冲突了。我的项目里面已经有一个 okhttp:3.8.1 了,这里导入这个库的时候,又将 okhttp:3.10.0 给导入进来了,直接排除掉就可以,具体说明文章末尾细讲!
至于 group 和 module,可以看我下面这个引入,类比下:
com.squareup.okhttp3:okhttp:3.10.0
2、全局删除
android{ //.... //剔除工程中所有的该依赖 configurations { all*.exclude group: 'org.hamcrest', module: 'hamcrest-core' } }
这个是一个很傻的办法,直接全局设定,把导入的某 jar 包全部删除,这样就不冲突了?也许打包是没问题了,只要用到功能必闪退吧!(貌似有人说要配合 Multidex 一起用,看看咯!)
3、开启 Multidex 功能
我是想不到 jar 包冲突和 Multidex 有什么关系,但是看到几篇博客说能解决问题,也顺便说一下吧!我个人认为 Multidex 就是解决 class 过多的,不知道是不是。
步骤 1:更改 build.grade
defaultConfig { ... // Enabling multidex support. multiDexEnabled true } dependencies { ... compile 'com.android.support:multidex:1.0.1' }
步骤 2:设置 Application 类
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); MultiDex.install(this); } }
步骤 3:更改 grade.properties
org.gradle.jvmargs=-XX:MaxHeapSize\=2048m -Xmx2048m
步骤 4:通过增大可用内存解决「:app:transformClassesForDexForDebug」异常,在 gradle.build 中指定 javaMaxHeapSize:
android { ... dexOptions { javaMaxHeapSize "4g" //specify the heap size for the dex process } }
4、强制修改版本
这个办法在网上见的多,大致就是在模块的 gradle 文件里面强制使用某一个版本的 jar 包,这样就不会下载两个 jar 包了。
我是发现没什么用,网上有的说放根目录,有的说放 android 里面,我不确定放哪啊!我是都试了,没效果,可能运行项目的姿势不对喽?
android{ //.... //放在这??? } //根节点??? configurations.all { //resolutionStrategy.force 'com.squareup.okhttp3:okhttp:3.10.0' resolutionStrategy.eachDependency { DependencyResolveDetails details -> def requested = details.requested if (requested.group == 'com.google.android.exoplayer') { if (!requested.name.startsWith("multidex")) { details.useVersion '2.9.3' } } } }
还有人说可以在工程的 gradle 中强制设置,我是发现也是没什么用,提一下。
allprojects { ... configurations.all { resolutionStrategy.force 'com.squareup.okhttp3:okhttp:3.10.0' } }
5、自行删除
这个方法我觉得可以解决特定问题,但局限性很大。
我们知道别人的依赖我们是无法修改的,但是自己本地 lib 是可以删除,如果是和我们本地的 jar 包冲突的话,我们删掉自己的就行了。
这个解决办法有局限性,一个是要求冲突的 jar 包在我们本地(可以操作),另一个如果我们用的版本较高,而别人的版本较低怎么办?那岂不是凉凉,此为下策!
6、使用 compileOnly
compileOnly 的形式引入库会只在编译时有效,不参与打包,它是解决一个什么问题呢?其实就是多个模块中,会冲突的库,让其中一个 implementation ,其他使用 compileOnly,最后出来能够共用一个库(当然要有一个)。
那这个办法和解决我们的问题有什么关联呢?其实这个办法和第二个方法类似,目的就在打包,引入的库的时候将 implementation 改为 compileOnly,让引入的库只在编译时有效,不会参与打包,这样就能够打包了。
这个问题也很明显,我要是能找到冲突的库,让它单独 compileOnly 固然能解决问题,可是事与愿违,我们冲突的库一般都是在别人的库里面,如果直接将所有内容以 compileOnly 形式导入,我们百分百要用到这个库里面的东西啊,一用就会闪退,最终只是自欺欺人罢了!
好了,上面就是解决依赖冲突的几种办法了,推荐第一个,其他有些鸡肋。