gradle如何下载sdk
gradle开始构建之前,会先确定需要参与构建的sdk以及他们的版本,并且下载到本地(当然也有可能使用缓存,本文不讨论这种情况),gradle的这个操作简单来说分为两个步骤:
1.确定sdk的版本号
-
静态版本号:
对于静态的版本号,gradle直接选择版本号最高的那个参与构建
[图片上传失败...(image-85489a-1601375116238)]
-
动态版本号,形如:com.xxx:sdk:1.1+,com.xxx:sdk:latest_version:
对于动态版本号,gradle将会遍历我们在build.gradle文件中定义的仓库,读取仓库中对应sdk的maven-matedata.xml文件,这个文件保存了当前仓库所拥有的该sdk的所有版本记录;不同的仓库类型获取版本信息的方式可能不同。本文仅讨论maven。
build.gradle文件中定义的repositories:
buildscript { repositories { google() jcenter() } }
这里很容易出现问题:由于gradle在确定动态版本号的时候,需要遍历所有的远程仓库,综合确定一个实际要使用的版本号,就会导致gradle在初始配置依赖的时候,非常的消耗时间(如果你本地没有缓存或者缓存过期了又或者你添加了新的仓库),像我们公司的项目经常会配置7+仓库,而一旦某一个仓库无法访问,gradle就会停止构建,导致打包经常失败(can not resolve);因为不同的仓库保存的SDK版本号可能不一致,所以gradle不可以忽略这种错误。
2.下载sdk
-
确定了需要参与构建的sdk以及他们的版本之后,下一步就是下载这些sdk了。
- 按照我们在build.gradle中配置的仓库,从第一个开始,按顺序查找;
- 如果在这个仓库中找到了所需要版本的sdk的pom文件,停止查找,开始下载,如果下载失败,则构建失败;如果当前仓库没有找到这个版本的pom文件,去下一个仓库查找;
- 如果在所有的仓库中都没有找到对应的pom文件,构建失败
如何优化
- 使用静态的版本号:个人不建议在项目中使用动态版本号,这就是一个炸弹,你不知道它什么时候突然升了个级,然后出现一些莫名其妙的问题。
不知道项目中哪个sdk的版本号是动态的?在项目的根目录运行下面的命令:
./gradlew app:dependencies > depts.txt
这个命令生成项目的依赖树并保存在depts.txt文件中,在依赖树中可以看到哪些sdk的版本号是动态的:
[图片上传失败...(image-56f6ba-1601375116238)]
这里动态依赖已经被固定为一个精确的版本了。如何固定版本?在app/build.gradle中配置,与android的配置同级
configurations.all { Configuration configuration -> configuration.resolutionStrategy { ResolutionStrategy resolutionStrategy -> resolutionStrategy.force "com.amap.api:location:5.1.0" resolutionStrategy.force "com.amap.api:map2d:6.0.0" resolutionStrategy.force "com.amap.api:search:7.4.0" } }
- 减少仓库配置,去掉一些无用的仓库配置,对仓库进行一个排序,把使用几率比较高,稳定的,速度高的排在前面。
额外扩展
- ContraintLayout的maven-metadata.xml文件,当我们使用动态版本号的时候,gradle会读取这个文件
<img src="//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/23140db7c4cf4eb188b3360ad9269974~tplv-k3u1fbpfcp-zoom-1.image" alt="image-20200929165346087" style="zoom:70%;" />
-
ContraintLayout 2.0.1版本的pom文件,gradle下载sdk之前会先读取这个文件
可以看到,ContraintLayout还依赖其他的sdk,这些被依赖进来的sdk版本在我们项目构建的时候也会参与sdk的版本号竞争中。如果我们想要排除掉(不依赖)这个sdk中的某个依赖项,可以在implementation的时候配置exclude。
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>androidx.constraintlayout</groupId>
<artifactId>constraintlayout</artifactId>
<version>2.0.1</version>
<packaging>aar</packaging>
<name>Android ConstraintLayout</name>
<description>ConstraintLayout for Android</description>
<url>http://tools.android.com</url>
<inceptionYear>2007</inceptionYear>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<name>The Android Open Source Project</name>
</developer>
</developers>
<scm>
<connection>git://android.googlesource.com/platform/tools/sherpa.git</connection>
<url>https://android.googlesource.com/platform/tools/sherpa</url>
</scm>
<dependencies>
<dependency>
<groupId>androidx.appcompat</groupId>
<artifactId>appcompat</artifactId>
<version>1.2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>androidx.core</groupId>
<artifactId>core</artifactId>
<version>1.3.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>androidx.constraintlayout</groupId>
<artifactId>constraintlayout-solver</artifactId>
<version>2.0.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
> 使用exclude排除掉constraintlayout中依赖的appcompat
>
> ```groovy
> implementation("androidx.constraintlayout:constraintlayout:2.0.1") {
> exclude group: 'androidx.appcompat', module: 'appcompat'
> }
> ```
网友评论