踩了两天gradle的坑,复盘一波。。
一、 关于gradle依赖
apply plugin: 'com.android.application'
android { ... }
dependencies {
// Dependency on a local library module
implementation project(":libraryName")
// Dependency on local binaries
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Dependency on a remote binary
implementation 'com.example.android:app-magic:12.3'
}
依赖类型:
1. 本地library依赖
implementation project(":libraryName")
直接依赖本地工程库的代码,libraryName需要在settings.gradle中使用include标签定义,告诉AndroidStudio本地有哪些model。
2. 本地二进制(jar)依赖
implementation fileTree(dir: 'libs', include: ['*.jar'])
用于依赖工程本地的jar文件,dir是module_name/目录下的jar文件(Gradle的路径是根据build.gradle下指定的路径,不是绝对路径)
依赖单个jar:
implementation files('libs/XXX.jar', 'libs/XXX.jar')
3.远程二进制依赖
implementation 'com.android.support:support-annotations:27.1.1'
最熟悉的一种依赖,常用与一些三方库依赖。它的全部写法是:
implementation group: 'com.android.support', name: 'support-annotations', version: '27.1.1'
version也可以写成27.1+的形式,但是不推荐,可能会由于库的版本升级造成风险点。在AS3.0之后大部分的project都要声明远程仓库(jcenter(),google(),maven等),在一些情况下这些声明由于网络环境原因会导致我们无法编译,如果没有科学手段,可以使用国内的一些镜像。
二、依赖配置
目前gradle版本支持的依赖配置有很多:implementation、api、compileOnly、runtimeOnly 和 annotationProcessor等等,比较常用的是api和implementation,官方更推荐使用implementation,api是已经废弃的compile的替代者。
-
api
api是compile的替代,它的功能和compile是完全一致的,api支持编译和运行时都能够访问model中的方法,但是如果有一个model添加了某个api的依赖,在其他model也能访问这个依赖的实现,这时候就有可能出现依赖冲突或者报错,这也是官方为什么更推荐使用implementation的原因。 -
implementation
implementation和compile对应,api和implementation都会将依赖添加到编译中并且一起打包,但是在编译时implementation并不会将依赖的实现暴露给其他model,只有运行时其他model才能访问它的实现,这样会使得gradle的构建效率提升,因为它能够减少gradle的重新编译model的次数。在开发过程中建议尽量使用implementation。
三、如何查看依赖树
当出现依赖冲突的时候,我们需要对依赖进行排查找出冲突的地方。这里推荐使用两种:(其他方法也可以,萝卜白菜各有所爱哈)
- gradlew命令
./gradlew 模块名:dependencies
这个命令会打印出该模块下的所有第三方类库的依赖情况,有多种展示情况,complie编译时的,Runtime运行时(打到APK包时)的。
- 插件GradleView
一个第三方插件,能够快速的查询出当前project的所有model的依赖,懒人必备~
四、依赖冲突
最近两天一直踩的坑,解冲突解到怀疑人生,根本原因其实是项目用的依赖版本较低,在依赖新的库的时候会和旧的库产生冲突,会报类似于下面的错误:
Program type already present com.example.TestLog
解决办法:
- 将相应的依赖升级至同一版本(如果依赖太多会导致长时间排查,十分消耗人力)
- 使用exclude,指定model在gradle加载时不编译(可能会导致同一个包下有不同的类会在库中使用,exclude会一起丢掉它们)
例如:
api (XXX){
exclude group: 'com.xxxx.xxx', module: 'xxx'
}
如:com.android.support:support-annotations:27.1.1
//将support-v4丢弃使用项目中的support-v4包
api (com.android.support:support-annotations:27.1.1){
exclude group: 'com.android.support', module: 'support-v4'
}
-
继续使用exclude,把缺失的类拷贝到自己的项目中(注意必须建一个相同的路径)
-
除了exclude,还有force(强制使用当前库版本),transitive(禁止依赖传递)等等,当然,需要对症下药~
网友评论