HarmonyOS鸿蒙最新Gradle常用命令与参数&依赖管理和版本决议,学生会面试试题

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

//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 的相应说明信息(这里只截取了一部分)


![](https://img-blog.csdnimg.cn/img_convert/2e598f9ce1e78bc90d4729cc7e4e6bfe.webp?x-oss-process=image/format,png)


##### 2.6.2 执行 Task



./gradlew
//or
./gradlew ::


可以在 AndroidStudio 右边栏的 Gradle 菜单下选择 Tasks 执行也是一样的效果


#### 2.7 依赖查看命令


依赖查看命令可以让我们更清晰的了解引入的依赖库,解决因为依赖导致的错误或者剔除一些不需要的依赖



./gradlew app:dependencies //输出 app 模块依赖树
//or
./gradlew dependencies > xxx.txt //输出依赖树到 xxx.txt 文件


![](https://img-blog.csdnimg.cn/img_convert/764dd216bef1a2680c46f47c2d390410.webp?x-oss-process=image/format,png)


依赖关系树后面有的会跟`(*)``(c)`有的又没有,代表如下意义:


1. `*` :表示该依赖项已被标记为被选中的版本。这意味着它是根据解析规则中的约束条件被选择的版本,而不是默认的最新版本。这通常是由于在项目的构建配置中明确指定了依赖项的版本或者存在其他依赖项对其版本有限制的情况。
2. `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'))`。通过动态参数,我们可以在打包过程中做一些差异化的构建。


![](https://img-blog.csdnimg.cn/img_convert/26d721e3a883ab8ee91d14db9148f403.webp?x-oss-process=image/format,png)


## 二、依赖管理和版本决议


在我们的开发中,经常会遇到各个模块中引入了相同的三方库,但是三方库版本又各不相同。有时候只是升级了一下某个依赖库存,结果运行就各种报错了。这部分课程将介绍一下 Gradle 的依赖管理方式和版本决议机制,弄明白 Gradle 是怎么把三方库引入到项目中的。在遇到同库不同版本的时候又是怎样决定使用哪个版本的。


![](https://img-blog.csdnimg.cn/img_convert/a529e037f3a6727f2d4e313646cc4f2e.webp?x-oss-process=image/format,png)


### 1、依赖管理


不使用 maven 方式接入三方库,我们一般都是直接导入 jar 包或者 aar 包。替换版本的时候又重新去导入新的版本的 jar 或者 aar。遇到导入了相同 jar 或者 aar 的时候还出现冲突编不过。如果我们基于 Gradle 来开发项目,则可以依靠 Gradle 比较灵活方便的对依赖库版本进行管理。下图是 Gradle 工作的大致示意图:


![](https://img-blog.csdnimg.cn/img_convert/3e813c0b959c3001306de905ba2b9273.webp?x-oss-process=image/format,png)


构建过程中,Gradle 会先从本地检索,找不到就挨个从远端找依赖库,然后缓存到本地。 我们也可以通过以下方式,开启离线编译,对于未指定版本号或者使用动态版本号的依赖使用本地的版本进行编译


![](https://img-blog.csdnimg.cn/img_convert/5620088dd490f2b8061ad6951c80f721.webp?x-oss-process=image/format,png)


#### 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,远端仓库起一个桥梁的作用,把开发者和依赖库作者连接起来。开发者、远端仓库、依赖库开发者三者关系大概如下图所示:


![](https://img-blog.csdnimg.cn/img_convert/341222df5c63c792aba07dd6de46538d.webp?x-oss-process=image/format,png)


1. 左侧是我们项目的开发过程,通过声明依赖库信息和配置远端仓库地址,从而找到我们想要的 Lib;
2. 中间为远端仓库,包含了丰富的 library/组件/插件;
3. 右侧是 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,我们可以看到更多依赖库的相关信息:


![](https://img-blog.csdnimg.cn/img_convert/000552f1b856ec257c90fd8233a1d4a2.webp?x-oss-process=image/format,png)


![](https://img-blog.csdnimg.cn/img_convert/f9a3a8cb664eb067b4bf0e32d68f8287.webp?x-oss-process=image/format,png)


在 Maven 依赖方式下可以更清晰的看出一个依赖库引用方式的结构:


* **groupId**:依赖库发布组织的名称,一般是公司域名倒写.包名;
* **artifactId**:项目名称,如果 groupId 包含了项目名称,这里就是子项目名称;
* **version**:版本号,这个库的具体版本号;


这里我们已系统设置的 DataReporter 这个 Lib 为例,发布端配置信息如下


![](https://img-blog.csdnimg.cn/img_convert/339c1ca6302498510c90e3e06f525846.webp?x-oss-process=image/format,png)


#### 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 也是一样的效果。


![](https://img-blog.csdnimg.cn/img_convert/6c505e8adc6ce34ee5a1987c48eb1778.webp?x-oss-process=image/format,png)


输出的依赖树包含了模块所有的直接依赖和间接依赖信息,从图中我们可以看到,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’


![](https://img-blog.csdnimg.cn/img_convert/1907b007c902f63ad02acfb717a88bee.webp?x-oss-process=image/format,png)


结论:同模块引入不同版本,以更高版本为准


**示例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”)
}
}


![](https://img-blog.csdnimg.cn/img_convert/5382af08d9070abe9f58745af03263d2.webp?x-oss-process=image/format,png)


![](https://img-blog.csdnimg.cn/img_convert/2afe3958cad53b6d689a506f2865d3ff.webp?x-oss-process=image/format,png)


结论:低版本中如果用 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’


![](https://img-blog.csdnimg.cn/img_convert/54b9643c2b32d4835cbad1c8ed80bd38.webp?x-oss-process=image/format,png)


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’


![](https://img-blog.csdnimg.cn/img_convert/fcab96c8950eae73b3bfd867af72f5ec.webp?x-oss-process=image/format,png)


结论:不同模块引入不同版本,以版本高的为准


**示例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”)
}
}


![](https://img-blog.csdnimg.cn/img_convert/c1366350c07b7909f2c06b4c0932a2da.webp?x-oss-process=image/format,png)


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’


![](https://img-blog.csdnimg.cn/img_convert/93ad6d08915de5a5ae1b88e672dfc391.webp?x-oss-process=image/format,png)


结论:子模块使用 strictly 强制低版本会报错,主模块使用 strictly 可以实现子模块降版本,可能导致子模块兼容问题。


**总结**


1. 默认规则总是取高版本覆盖低版本
2. strictly 关键字主工程可以实现降低编译版本
3. 同模块或者子模块使用 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 版本管理(提前预防)


在项目实施过程中我们一般有以下方式对依赖版本进行约束:


1. 配置统一的 gradle.config 放在云端统一进行维护,所有工程要增加三方依赖都通过这个文件进行配置,这样可以做到编译过程各个module三方依赖的版本统一。像我们现在项目中统一配置的 config.gradle。目前看应该是项目级别进行了配置,其实也可以迁移到云端统一管理,多项目共用
2. 模块配置一个公共的 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’

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!


img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

})
//去除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’

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!


[外链图片转存中…(img-q2i7vjUr-1715833637386)]
[外链图片转存中…(img-E9Q2qs28-1715833637387)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化的资料的朋友,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值