一、Gradle 常用指令与参数
本课程全程依据 Gradle8.0 环境
1、Gradle 指令
介绍 gradle 指令之前咱们先来了解下 gradle 指令怎样在项目中履行。
1.1、gradlew
gradlew 即 Gradle Wrapper,在学习小组的榜首课时现已介绍过了这儿就不多赘述。提一下履行指令,一般网上都是 windows 下用 gradlew
; Mac 或许 Linux 下用 ./gradlew
。实际上 AS Dolphin 2021.3.1 后的版别由于默许终端切换成 powershell 所以指令变成了 .gradlew
或许 ./gradlew
都能够。咱们接下来看看 gradlew
脚本的内容(Android Studio 项目根目录 gradlew 文件):
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> (.*)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname "$PRG"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS "-Xdock:name=$APP_NAME" "-Xdock:icon=$APP_HOME/media/gradle.icns""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`=""$arg""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\n "$i" | sed "s/'/'\\''/g;1s/^/'/;$s/$/' \\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS ""-Dorg.gradle.appname=$APP_BASE_NAME"" -classpath ""$CLASSPATH"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
首要干了这几件事
- 设置 APP_HOME
- 装备默许的 JVM 选项
- 设置 CLASSPATH 路径,即指定 gradlew-wrapper.jar 路径
- 查看 JAVA 环境装备等
1.2、指令大全
履行 ./gradlew --help
gradle 会为咱们输出协助信息:(这儿只列出了部分,更多能够自己敲指令去看看)
PS D:workspaceGradleDemo> ./gradlew --help
To see help contextual to the project, use gradlew help
USAGE: gradlew [option...] [task...]
-?, -h, --help Shows this help message.
-b, --build-file Specify the build file. [deprecated]
--build-cache Enables the Gradle build cache. Gradle will try to reuse outputs from previous builds.
-c, --settings-file Specify the settings file. [deprecated]
--configuration-cache Enables the configuration cache. Gradle will try to reuse the build configuration from previous builds. [incubating]
--configuration-cache-problems Configures how the configuration cache handles problems (fail or warn). Defaults to fail. [incubating]
--configure-on-demand Configure necessary projects only. Gradle will attempt to reduce configuration time for large multi-project builds. [incubating]
--console Specifies which type of console output to generate. Values are 'plain', 'auto' (default), 'rich' or 'verbose'.
--continue Continue task execution after a task failure.
-D, --system-prop Set system property of the JVM (e.g. -Dmyprop=myvalue).
-d, --debug Log in debug mode (includes normal stacktrace).
--daemon Uses the Gradle daemon to run the build. Starts the daemon if not running.
--export-keys Exports the public keys used for dependency verification.
-F, --dependency-verification Configures the dependency verification mode. Values are 'strict', 'lenient' or 'off'.
--foreground Starts the Gradle daemon in the foreground.
-g, --gradle-user-home Specifies the Gradle user home directory. Defaults to ~/.gradle
-I, --init-script Specify an initialization script.
-i, --info Set log level to info.
-p, --project-dir
这些指令也是能够简写的,例如 --help
能够简写为 -?
、-h
1.3、指令格式
gradle 指令的整体格式如下:
gradle [taskName...] [--option-name...]
2 gradle 常见指令
依据指令的功用目的,Gradle 指令大致能够分为下图的这些类型。
2.1 gradle 本身相关
2.1.1 查看 gradle 版别
查看 gradle 版别一般咱们都是直接看项目中的 gradle.property 文件,里面的 distributionUrl
参数。除了这种办法,咱们还能够经过gradle 指令查看:
输入:
./gradlew -version
//or
./gradlew -v
输出:
------------------------------------------------------------
Gradle 8.0
------------------------------------------------------------
Build time: 2023-02-13 13:15:21 UTC
Revision: 62ab9b7c7f884426cf79fbedcf07658b2dbe9e97
Kotlin: 1.8.10
Groovy: 3.0.13
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 17.0.8 (Amazon.com Inc. 17.0.8+7-LTS)
OS: Mac OS X 13.0.1 x86_64
2.1.2 gradle 版别晋级
1、直接修正工程 gradle/wrapper/gradle-wrapper.properties 文件的 distributionUrl
修正 gradle 版别
2、File>Project Structure 修正 AndroidGradle Plugin Version 和 Gradle 的版别然后 apply
3、运用指令行输入指令晋级
./gradlew wrapper --gradle-version xxx
2.1.3 列出某个指令即将履行的一切使命(并不是真的履行它)
./gradlew xxx --dry-run
其中xxx便是要履行的指令,咱们在学习的时分能够经过这个指令来快速的查看某个指令即将履行哪些使命。也便利快速比照类似功用的指令在履行进程中有哪些差异。
2.2 编译指令
2.2.1 编译打包
./gradlew build
//or
./gradlew assemble
这两个指令都是编译并输出全部类型的包。他们之间不同在于,build
指令是包含了 assemble
指令的全生命周期的,从上面的 task --all
指令阐明也能够看出。下面的这个图能够更直观的反映:
分别履行 ./gradlew assemble --dry-run
和 ./gradlew assemble --dry-run
指令,把输出成果进行比照。不同便是 build
指令会在 assemble
之后履行额定的 check
使命
2.2.2 编译 debug 包
./gradlew assembleDebug
//or
//反映
./gradlew installDebug
两个使命前面过程共同,最终一步不相同,分别是履行 :app:assebmleDebug
和 :app:installDebug
2.2.3 编译 release 包
./gradlew assembleRelease
//or
./gradlew installRelease
两个使命前面过程共同,最终一步不相同,分别是履行 :app:assebmleRelease
和 :app:installRelease
2.2.4 编译并打印日志
./gradlew assembleDebug --info
//or
./gradlew assembleRelease --info
加上 –info,编译日志会更完好,便利定位问题。
2.3 清除指令
./gradlew clean
等同于 Build > Clean Project,会清除构建目录下的产品
2.4 卸载指令
./gradlew uninstallDebug
//or
./gradlew uninstallRelease
这个指令是直接卸载连接设备上的当前项目安装包,跟 adb 指定包名进行卸载相同
2.5 调试指令
当咱们运用 gradle 进行打包报错时,调试指令就能够帮咱们更便利的定位出问题原因
2.5.1 编译并输出库房日志
./gradlew assembleDebug --stacktrace
//or
./gradlew assembleDebug -s
或许能够在参数前加上 –full 输出更详细的日志信息
./gradlew assembleDebug --full-stacktrace
//or
./gradlew assembleDebug --full-s
2.5.2 设置日志级别
Gradle 的日志分级
Level | 作用 |
---|---|
ERROR | 过错 |
WARNING | 警告 |
LIFECYCLE | 生命周期 |
INFO | 信息 |
DEBUG | 调试 |
TRACE | 盯梢 |
日志过滤
过滤指令 | 作用 |
---|---|
-q 或 -quiet | 只显现 ERROR 和 WARNING 日志 |
–i 或 –info | 显现 INFO 及以上日志 |
-d 或 –debug | 显现 DEBUG 及以上日志 |
示例:
./gradlew assembleDebug -e
2.6 使命相关指令
2.6.1 查看项目 gradle task
./gradlew tasks //只列出要害的 task
//or
./gradlew tasks --all //一切的 task 都将列出
这个指令将列出项目一切要履行的 task,而且会有这个 task 的相应阐明信息(这儿只截取了一部分)
2.6.2 履行 Task
./gradlew <taskName>
//or
./gradlew :<moduleName>:<taskName>
能够在 AndroidStudio 右边栏的 Gradle 菜单下挑选 Tasks 履行也是相同的作用
2.7 依托查看指令
依托查看指令能够让咱们更明晰的了解引进的依托库,处理由于依托导致的过错或许剔除一些不需求的依托
./gradlew app:dependencies //输出 app 模块依托树
//or
./gradlew dependencies > xxx.txt //输出依托树到 xxx.txt 文件
依托联系树后边有的会跟(*)``(c)
有的又没有,代表如下含义:
-
*
:表明该依托项已被标记为被选中的版别。这意味着它是依据解析规矩中的束缚条件被挑选的版别,而不是默许的最新版别。这通常是由于在项目的构建装备中明确指定了依托项的版别或许存在其他依托项对其版别有限制的情况。 -
c
:表明该依托项是由于抵触处理而被强制挑选的版别。当项目中存在多个依托项,它们对同一依托的版别有不同的要求时,Gradle 将尝试处理这些抵触。假如无法找到满意一切依托项的版别,Gradle 将挑选一个版别并标记为抵触(conflict)。(c)
标记表明该依托项是由于抵触处理而被强制挑选的版别。
举个例子:
假定项目 A 依托于库 X 的版别 1.0,而项目 B 依托于库 X 的版别 2.0。这两个项目都作为依托项添加到同一个项目 C 中。现在,项目 C 需求一起满意项目 A 和项目 B 的依托。
Gradle 将尝试处理这个抵触,它会查看是否有一个版别能够一起满意项目 A 和项目 B 的依托。假如存在满意一切依托项的版别,Gradle 将挑选该版别,并将其标记为被选中的版别(*)
。
可是,假如无法找到满意一切依托项的版别,Gradle 将不得不做出一个决策。在这种情况下,Gradle 会挑选一个版别,并将其标记为抵触(c)
。这表明所选的版别是为了处理抵触而被强制挑选的,或许无法完全满意一切依托项的要求。
2.8 功能相关指令
2.8.1 运用本地缓存版别离线编译
./gradlew assembleDebug --offline
也能够在AndroidStudio 侧边栏可视化敞开关闭。不同在于,假如没敞开离线编译,每次编译的时分都会去查看版别,关于没指定版别号或许动态版别号的依托每次都会以最新的版别进行编译。
2.8.2 构建缓存
./gradlew assembleDebug --build-cache //敞开
./gradlew assembleDebug --no-build-cache //不敞开
2.8.3 装备缓存
./gradlew assembleDebug --configuration-cache //敞开
./gradlew assembleDebug --no-configuration-cache //不敞开
2.8.4 并行构建
./gradlew assembleDebug --parallel //敞开
./gradlew assembleDebug --no-parallel //不敞开
功能相关的这几个指令履行作用,和直接在 gradle.properties 中装备作用是相同的。
2.8.5 编译功能陈述
./gradlew assembleDebug --profile
会在项目目录的 build
> reports
> profile
路径下生成陈述文件
./gradlew assembleDebug --scan
会生成更详细的在线陈述,首次履行会邮箱验证授权,完成后会输出一个链接。
2.9 动态传参指令
./gradlew assembleDebug -PisTest=true
build.gradle 中经过如下办法获取参数值
if(project.hasProperty("isTest")){
// do something
}else{
// do something else
}
经过 hasProperty 来获取指令行的参数
project.getProperty("isTest")
上面的办法都是判断参数是否存在,那么怎样获取参数的值呢?
if(project.hasProperty("isTest")){
println("******hasProperty isTest yes******")
if(Boolean.valueOf(project.getProperty('isTest')){
println("******property isTest true******")
}else{
println("******property isTest false******")
}
}else{
println("******hasProperty isTest no******")
}
获取参数的数据类型需求根本数据类型转换成对应的类型,即 XXX.valueOf(getProperty('key'))
。经过动态参数,咱们能够在打包进程中做一些差异化的构建。
二、依托办理和版别抉择
在咱们的开发中,经常会遇到各个模块中引进了相同的三方库,可是三方库版别又各不相同。有时分仅仅晋级了一下某个依托库存,成果运转就各种报错了。这部分课程将介绍一下 Gradle 的依托办理办法和版别抉择机制,弄理解 Gradle 是怎样把三方库引进到项目中的。在遇到同库不同版别的时分又是怎样抉择运用哪个版别的。
1、依托办理
不运用 maven 办法接入三方库,咱们一般都是直接导入 jar 包或许 aar 包。替换版别的时分又重新去导入新的版别的 jar 或许 aar。遇到导入了相同 jar 或许 aar 的时分还呈现抵触编不过。假如咱们依据 Gradle 来开发项目,则能够依托 Gradle 比较灵活便利的对依托库版别进行办理。下图是 Gradle 工作的大致示意图:
构建进程中,Gradle 会先从本地检索,找不到就挨个从远端找依托库,然后缓存到本地。 咱们也能够经过以下办法,敞开离线编译,关于未指定版别号或许运用动态版别号的依托运用本地的版别进行编译
1.1 声明依托
1.1.1 装备 maven 和依托信息
声明 maven 依托包含两部分:
- 库房装备 我这儿是在 gradle 8.0 的环境下演示的。装备信息在 projetc > settings.gradle 下,低版别装备信息一般在 project > build.gradle 下
pluginManagement {
repositories {
//指定 maven 库房的地址
maven { url "https://www.jitpack.io" }
google()
//maven 官方库房地址
mavenCentral()
//自定义 gitlab 库房作为 maven 地址
maven {
url "https://gitee.com/monkeies/maven/raw/master"
}
//本地 maven 库房地址
maven {
url uri("/Users/pandaq/WorkSpace/AndroidProjects/Aizhong/Maven/")
}
//http 地址需求装备 allowInsecureProtocol = true
maven {
url 'http://xxx.xxx.xxx/xxx/'
allowInsecureProtocol = true
}
}
}
- 依托库装备 依托库的装备信息在各个 module 的 build.gradle 下
implementation 'com.airbnb.android:lottie:6.1.0'
1.1.2 依托类型
- 本地模块依托
- 本地二进制文件依托
- 远端二进制文件依托
dependencies {
// Dependency on a local library module
implementation project(':mylibrary')
// Dependency on local binaries
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Dependency on a remote binary
implementation 'com.example.android:app-magic:12.3' }
1.2 远端库房
1.1.1 中咱们装备的 repositories ,里面的 url 便是依托项上川岛远端库房的 url,远端库房起一个桥梁的作用,把开发者和依托库作者连接起来。开发者、远端库房、依托库开发者三者联系大概如下图所示:
- 左侧是咱们项目的开发进程,经过声明依托库信息和装备远端库房地址,从而找到咱们想要的 Lib;
- 中间为远端库房,包含了丰富的 library/组件/插件;
- 右侧是 Lib 组件的开发者,把代码经过 aar/jar的方式打包到远端库房供给给运用方;
1.3 GAV
GAV 即 groupId、artifactId、version ,maven 依据这三个维度的规矩确认 Library 的唯一性。咱们日常的依托引进是这样的:
implementation 'com.airbnb.android:lottie:6.1.0'
完好的内容其实是这样的:
implementation group: 'com.airbnb.android', name: 'lottie', version: '6.1.0'
翻开 maven 查找对应的 Library,咱们能够看到更多依托库的相关信息:
在 Maven 依托办法下能够更明晰的看出一个依托库引证办法的结构:
- groupId:依托库发布组织的称号,一般是公司域名倒写.包名;
- artifactId:项目称号,假如 groupId 包含了项目称号,这儿便是子项目称号;
- version:版别号,这个库的详细版别号;
这儿咱们已系统设置的 DataReporter 这个 Lib 为例,发布端装备信息如下
1.4 依托传递
Gradle 除了帮咱们下载依托,还供给了依托传递的能力。依据咱们的依托引进办法不同,有着不同的依托传递作用。
依托办法 | 阐明 | 示例 |
---|---|---|
implementation | 编译时对模块可用,运转时对模块的顾客可用 | A 依托 B,B 依托 C;在编译和运转时 B均可用 C的代码;A 不能编译时用 C 代码,但运转时可拜访 C 代码。 |
api | 编译和运转时对模块和模块的顾客都可用 | A 依托 B,B 依托 C;编译和运转时 A、B 都能够用 C 的代码 |
compileOnly | 仅编译时对模块可用,编译和运转时对模块顾客不可用,运转时对一切都不可用 | A 依托 B,B 依托 C;仅编译时 B 能够拜访 C,运转时是没有 C 的任何代码的 |
runtimeOnly | 仅在运转时对模块和其顾客可用 | A 依托 B,B 依托 C;A、B都无法调用 C 的代码,可是 C 的代码会被打包到 apk 中,一般用于组件化隔离代码。 |
2、版别抉择
已然各个模块都能引进依托,而且依托还具有传递性,那么必定存在某两个或几个模块都引进了某个依托库。当他们引进版别不相同的时分问题就来了,最终构建项目时以哪个版别的依托库为准呢?
2.1 依托信息
前面课程现已讲过经过./gradlew app:dependencies
这个指令,咱们能够输出项目的依托树。经过 build –scan,或许AndroidStudio 的 Gradle 侧边栏 Gradle > app > help > dependencies 也是相同的作用。
输出的依托树包含了模块一切的直接依托和直接依托信息,从图中咱们能够看到,okhttp 是有4.9.3
和 4.10.0
两个版别的。图的 4.9.3 -> 4.10.0
表明 lib
模块中的版别被拔高到了 4.10.0
,由于 app 中引进了更高的 4.10.0 版别。接下来咱们一起来了解一下,gradle 是以怎样的规矩来抉择用哪个版别的。
2.2 抉择规矩
咱们直接经过不同的示例来了解 gradle 的版别抉择规矩:
示例1:同模块不同版别
implementation'com.squareup.okhttp3:okhttp:4.10.0'
implementation'com.squareup.okhttp3:okhttp:4.9.3'
定论:同模块引进不同版别,以更高版别为准
示例2:同模块运用强制要害字
//app
implementation'com.squareup.okhttp3:okhttp:4.10.0'
implementation('com.squareup.okhttp3:okhttp:4.9.3'){
version{
structly("4.9.3")
//strictly("4.10.0")
}
}
定论:低版别中假如用 strictly 强制低版别会报错,强制高版别会给高版别标识 strictly
示例3:不同同模块不同版别
1、app 中引进 4.10.0,lib 中引进 4.9.3
//app
implementation'com.squareup.okhttp3:okhttp:4.10.0'
//lib
implementation'com.squareup.okhttp3:okhttp:4.9.3'
2、app 中引进 4.9.3,lib 中引进 4.10.0
//app
implementation'com.squareup.okhttp3:okhttp:4.9.3'
//lib
implementation'com.squareup.okhttp3:okhttp:4.10.0'
定论:不同模块引进不同版别,以版别高的为准
示例4:子模块运用强制要害字
1、app 引进4.10.0,lib 中强制 4.9.3
//app
implementation'com.squareup.okhttp3:okhttp:4.10.0'
//lib
implementation('com.squareup.okhttp3:okhttp:4.9.3'){
version{
strictly("4.9.3")
}
}
2、app 强制4.9.3,lib 中引进4.10.0
//app
implementation('com.squareup.okhttp3:okhttp:4.9.3'){
version{
strictly("4.9.3")
}
}
//lib
implementation'com.squareup.okhttp3:okhttp:4.10.0'
定论:子模块运用 strictly 强制低版别会报错,主模块运用 strictly 能够实现子模块降版别,或许导致子模块兼容问题。
总结
- 默许规矩总是取高版别覆盖低版别
- strictly 要害字主工程能够实现降低编译版别
- 同模块或许子模块运用 strictly 降版别会直接报错
2.3 版别号规矩
gradle 版别抉择时的版别号规矩如下表所示:
分类 | 示例 | 抉择成果 | 阐明 |
---|---|---|---|
全数字,段数不同 | 1.2.3 vs 1.3 | 1.3 | 段数从左到右比较,高的胜 |
全数字,段数相同 | 1.2.3 vs 1.2.4 | 1.2.4 | 段数从左到右比较,高的胜 |
全数字,段数相同,位数不同 | 1.2.10 vs 1.2.3 | 1.2.10 | 段数从左到右比较,高的胜 |
全数字,段数不同 | 1.2.3 vs 1.2.3.0 | 1.2.3.0 | 段数多的胜 |
段数相同,字母比较 | 1.2.a vs 1.2.b | 1.2.b | 字母大胜 |
段数相同,数字与非数字 | 1.2.3 vs 1.2.abc | 1.2.3 | 数字优先于字母 |
别的 gradle 也支撑版别号范围选项,如[1.0,)
、[1.1,2.0)
、latest.release
等
2.4 抵触处理
当项目比较复杂,依托层级和module较多的时分,许多依托传递就变得不可控了,时常会遇到各种版别依托抵触。不论选用哪种办法,咱们都需求有一个抉择机制,确保依托版别大局的唯一性,大家遵循这个机制进行依托办理才能尽或许的防止这个问题。
2.4.1 版别办理(提早预防)
在项目施行进程中咱们一般有以下办法对依托版别进行束缚:
- 装备统一的 gradle.config 放在云端统一进行维护,一切工程要增加三方依托都经过这个文件进行装备,这样能够做到编译进程各个module三方依托的版别统一。像咱们现在项目中统一装备的 config.gradle。目前看应该是项目级别进行了装备,其实也能够迁移到云端统一办理,多项目共用
- 模块装备一个公共的 module_build.gradle,里面能够把有必要项比方 kotlin 、androidx 这些依托放在里面,运用模块再 apply from 的方式引进进去。
2.4.2 强制版别(暂时弥补)
项目施行半途遇到抵触了,再去统一版别显然不现实,那么咱们有什么小范围的暂时弥补措施呢:
1、exclude 独自去掉某个依托的抵触
//去除com.github.niorgai:StatusBarCompat:2.1.3引证的com.android.support包下内容
implementation('com.github.niorgai:StatusBarCompat:2.1.3') {
exclude group: 'com.android.support'
})
//去除module引证的'com.google.code.findbugs:jar305'的相关内容
implementation(project(':downlibrary')) {
exclude group: 'com.google.code.findbugs', module: 'jsr305'
}
2、去掉一切 module 中的指定依托
configurations {
implementation.exclude group: 'com.example', module: 'lib'
}
lib 中的依托变成了 app 中的 4.10.0 版别,而且没有以来抵触标识
3、强制一切module运用指定版别
//app build.gradle 中装备
configurations.configureEach{
resolutionStrategy{
force'com.squareup.okhttp3:okhttp:4.11.0'
}
}
app 中版别由 4.10.0 升到了 4.11.0;lib1 版别由 4.9.0 晋级到了 4.11.0;lib 版别由 4.10.0 晋级到了4.11.0
2.4.3 面向 Bug 编程
敞开版别抵触强检测形式,此形式下编译只要有版别抵触就会报错,再反过去顺藤摸瓜处理版别抵触。
configurations.configureEach{
resolutionStrategy{failOnVersionConflict()}
}