Gradle 依赖管理

前言 :依赖管理 在我们android项目中有非常重要的使用,如果对依赖管理没有清晰的认识,在遇到依赖冲突等问题的时候会碰到很多麻烦。

了解依赖管理

在大多数情况下,项目都要依赖lib形式的可重用功能,还有很多项目可能被切分成多个单独的子工程来构成模块系统。依赖管理是一种可以让项目自动化的定义、解析,及使用依赖的技术。Gradle提供了强大的依赖管理支持。Gradle中实现了现代软件项目的各种典型场景。

Gradle资源库

在Gradle中存储模块的地方就叫做资源库。

定义了资源库之后,Gradle就知道怎么样查找和检索模块。资源库有两种方式:本地库和远程库。在运行时,如果相应的任务需要,那么Gradle就需要定位依赖的声明,依赖可能需要从远程库下载,也可能从本地库检索或者是在多项目构建中的其他项目。这个过程就叫做依赖解析。

一旦解析,解析机制就会存储依赖的底层文件作为本地缓存,之后的构建会重用这些文件,而不用再到远程库下载。

模块还能提供一些其他的元数据,元数据是描述模块更详细信息的数据,比如在资源库中的坐标,项目的信息等。(group, name, version)

添加依赖仓库

在build.gradle中使用allprojects{}对所有的工程进行配置,使用repositories{}添加依赖仓库。google():添加一个在 Google 的 Maven 存储库中查找依赖项的存储库mavenCenteral():添加一个在 Maven 中央存储库中查找依赖项的存储库。jcenter()添加一个在 Bintray 的 JCenter 存储库中查找依赖项的存储库。

注意jecnter即将关闭,改用mavenCentral。如果有自己发布在jcenter的依赖库,需要迁移到mavenCentralAS高版本中也默认的将jcenter()改成了mavenCenteral()

mavenLocal()添加一个在本地 Maven 缓存中查找依赖项的存储库。

maven{}:指定某个maven仓库的地址,使用url(path)方法来添加。

ivy{}:指定某个ivy仓库地址,使用url(path)方法来添加。

Gradle依赖范围

在Gradle构建脚本中开发者可以把依赖定义到不同的范围中,比如编译源码或者执行测试。在Gradle中依赖的范围叫依赖项配置。

Gradle插件内置了几种方式的依赖项配置:

implementation、api、compileOnly、runtimeOnly、annotationProcessor、lintChecks

intPublish ...apk/compile/provided已被废弃

在build.gradle中使用dependencies{}添加依赖项配置。

自定义依赖项配置

添加自定义依赖项配置,就可以使用该依赖项配置添加依赖:

configurations {

    abc {

        println "abc"

    }

}

// 在dependencies{}中使用:abc 'androidx.core:core-ktx:1.2.0'

implementation

Gradle会将依赖项添加到编译类路径,并将依赖项打包到构建输出。不过,当您的模块配置 implementation依赖项时,会让Gradle了解您不希望该模块在编译时将该依赖项泄露给其他模块。也就是说,其他模块只有在运行时才能使用该依赖项。

使用此依赖项配置代替api或compile(已弃用)可以显著缩短构建时间,因为这样可以减少构建系统需要重新编译的模块数。例如,如果implementation依赖项更改了其API,Gradle 只会重新编译该依赖项以及直接依赖于它的模块。大多数应用和测试模块都应使用此配置

api

Gradle会将依赖项添加到编译类路径和构建输出。当一个模块包含 api 依赖项时,会让 Gradle 了解该模块要以传递方式将该依赖项导出到其他模块,以便这些模块在运行时和编译时都可以使用该依赖项

此配置的行为类似于 compile(现已弃用),但使用它时应格外小心,只能对您需要以传递方式导出到其他上游消费者的依赖项使用它。这是因为,如果api依赖项更改了其外部API,Gradle 会在编译时重新编译所有有权访问该依赖项的模块。因此,拥有大量的api依赖项会显著增加构建时间。除非要将依赖项的API公开给单独的模块,否则库模块应改用implementation依赖项。

annotationProcessor

如需添加对作为注解处理器的库的依赖,您必须使用 annotationProcessor 配置将其添加到注解处理器的类路径。这是因为,使用此配置可以将编译类路径与注释处理器类路径分开,从而提高构建性能。如果Gradle在编译类路径上找到注释处理器,则会禁用避免编译功能,这样会对构建时间产生负面影响(Gradle 5.0 及更高版本会忽略在编译类路径上找到的注释处理器)。

如果JAR文件包含以下文件,则Android Gradle插件会假定依赖项是注释处理器

META-INF/services/javax.annotation.processing.Processor如果插件检测到编译类路径上包含注解处理器,则会产生构建错误

compileOnly

Gradle只会将依赖项添加到编译类路径(也就是说,不会将其添加到构建输出)。如果您创建Android模块时在编译期间需要相应依赖项,但它在运行时可有可无,此配置会很有用

如果您使用此配置,那么您的库模块必须包含一个运行时条件,用于检查是否提供了相应依赖项,然后适当地改变该模块的行为,以使该模块在未提供相应依赖项的情况下仍可正常运行。这样做不会添加不重要的瞬时依赖项,因而有助于减小最终APK的大小。此配置的行为类似于provided(现已弃用)。

查看模块依赖项

要想查看整个项目的依赖传递关系,使用命令:

gradlew app:dependencies --configuration releaseRuntimeClasspath

x.x.x (*) 该依赖已经有了,将不再重复依赖。

x.x.x -> x.x.x 该依赖的版本被箭头所指的版本代替。 

x.x.x -> x.x.x(*) 该依赖的版本被箭头所指的版本代替,并且该依赖已经有了,不再重复依赖。

依赖传递导致的冲突

Gradle依赖管理进行了优化:

如果项目存在同一个依赖库的多个版本,默认选择最高版本。

Gradle会自动排除重复的依赖。

Gradle默认支持依赖传递。

既然Gradle已经自动做了这些优化,为何还会出现问题?

当引入一个第三方库,该库中也依赖了Android支持库,且支持库的版本和当前版本不一致。这种情况下,Gradle会自动选择最高的版本,导致不兼容的问题。

如果同时依赖一个group下的全量库,又依赖了这个group其中一个分库,如果这两个库版本不统一,就导致了依赖冲突问题。最典型的就是support-v424.2.0版本开始的分库导致的问题。androidx包和support包的冲突问题。

排除传递依赖项

随着应用的范围不断扩大,它可能会包含许多依赖项,包括直接依赖项和传递依赖项(应用中导入的库所依赖的库)。如需排除不再需要的传递依赖项,可以使 exclude关键字

dependencies {

    implementation('some-library') {

        exclude group: 'com.example.imgtools', module: 'native'

    }

}

使用全部排除:

// 在configurations{} 中添加下面节点

configuration{

    all*.exclude module: "support-fragment"

}

Froce强制指定

关于依赖传递的几个问题

依赖传递针对的是编译时能被上层模块直接使用。

implementation与api:使用implementation添加依赖项,在编译时不进行依赖传递但是在运行时依然可以使用其内部依赖项 (通过反射的方式调用)

 

使用api添加依赖项会进行依赖传递,但只针对上一层模块而言。

setTranstive:在添加依赖项时,如果设置transitive为false,表示关闭依赖传递。即内部的所有依赖将不会添加到编译和运行时的类路径

依赖传递始终遵循Gradle依赖管理的优化:即默认情况下选择最高版本的依赖项 (除非对依赖项设置了force为true强制优先使用该版本),同一个依赖项会自动被排除

所以 implementation 在 api 的选择上肯定优先选择implementation , api 的适用场景是多module 依赖,比如 app 工程依赖了 module A ,同时module A 又需要依赖了module B,app工程也需要去依赖module B,这个时候避免重复依赖module,可以使用module A api 依赖的方式去依赖module B,app工程只需要依赖module A 即可。

 

 

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值