补齐Android技能树 - 玩转Gradle(一) _ 小册免费学(1)

进程id为10276 → 进程处于空闲状态(BUSY表示正在构建任务) → 附加信息:6.1.1,打开任务管理器可以定位到此进程:

我们都知道java代码编译成class字节码后运行在JVM上,那就用jdk自带的 jvisualvm.exe 查看一波具体信息:

行吧,就是 daemon 守护进程,进程名为GradleDaemon,所以为啥要让一个守护进程常驻后台呢?

这得先提一提Maven了:

Maven在构建时,会启动一个Maven的JVM进程,构建结束后会关闭此进程,每使用一次Maven构建都要启动一次,其中load所需的jar文件是一个相当耗时的过程。

而Gradle 3.0之后,默认使用Daemon模式:

启动一个非常轻量的client JVM进程,只用于和后台的deamon JVM进程通信。构建完client进程关闭,而deamon进程仍然保留(处于IDLE空闲状态),下次需要构建时,直接启用deamon进程,减少构建的耗时等待。deamon进程默认后台保留三个小时,在此时间段没有被启动则关闭。

0x3、Gradle配置

Gradle配置的地方有三处,参数优先级依次如下:

命令行参数 > ~/.gradle/gradle.properties > 项目根目录/gradle.properties

罗列下较常用的命令行选项,大概过一下有个印象即可,用到再查(更多详细内容可参见:官方文档)

命令结构

gradle [taskName…] [–option-name…]

增量编译:同一个项目中, 同一个 task除非有必要, 否则不会被无意义的执行多次;

缓存:无论是否在同一个项目,只要Task输入没变就复用缓存结果,不必真的执行task;

Tasks执行

gradle myTask # 执行某个Task
gradle :my-subproject:taskName # 执行子项目中的Task
gradle my-subproject:taskName # 同上,不指定子项目,会执行所有子项目的此Task,如gradle clean;
gradle task1 task2 # 运行多个Task
gradle dist --exclude-task test # 将某个task排除在执行外
gradle dist -x test # 同上
gradle test --rerun-tasks # 强制执行UP-TO-DATE的Task,即不走增量编译,执行全量编译;
gradle test --continue # 默认情况下,一旦Task失败就会构建失败,通过此参数可继续执行;

常见任务(和插件间的Task约定)

gradle build
gradle run
gradle check
gradle clean # 删除构建目录

构建细节

gradle projects # 列出所有子项目
gradle tasks # 列出所有Task(分配给任务组的Task)
gradle tasks --group=“build setup” # 列出特定任务组的Task
gradle tasks --all # 列出所有Task
gradle -q help --task libs # 查看某个Task的详细信息
gradle myTask --scan # 生成可视化的编译报告
gradle dependencies # 列出项目依赖
gradle -q project:properties # 列出项目属性列表

调试选项

-?,-h,–help # 帮助信息
-v,–version # 版本信息
-s, --stacktrace # 打印出异常堆栈跟踪信息;
-S, --full-stacktrace # 比上面更完整的信息;

性能相关

–build-cache # 复用缓存
–no-build-cache # 不复用缓存,默认
–max-workers # 最大处理器数量
–parallel # 并行生成项目
–no-parallel # 不并行生成项目
–priority # Gradle启动的进程优先级
–profile # 生成性能报告

守护进程

–daemon # 使用deamon进程构建
–no-daemon # 不使用deamon进程构建
–foreground # 前台进程启动deamon进程
–status # 查看运行中和最近停止的deamon进程;
–stop # 停止所有同一版本的deamon进程;

日志选项

-q, --quiet # 只记录错误
-w, --warn
-i, --info
-d, --debug
–console=(auto,plain,rich,verbose) # 指定输出类型
–warning-mode=(all,fail,none,summary) # 指定警告级别

执行选项

–include-build # 复合构建
–offline # 离线构建
–refresh-dependencies # 强制清除依赖缓存
–dry-run # 在不实际执行Task的情况下看Task执行顺序
–no-rebuild # 不重复构建项目依赖

环境选项

-b, --build-file # 指定构建文件
-c, --settings-file # 指定设置文件
-g, --gradle-user-home # 指定默认.Gradle目录
-p, --project-dir # 指定Gradle的开始目录
–project-cache-dir # 指定缓存目录,默认.gradle
-D, --system-prop # 设置JVM系统属性
-I, --init-script # 指定初始化脚本
-P, --project-prop # 指定根项目的项目属性;

Tips:有些属性支持在gradle.properties文件中进行配置,就不用每次命令行输入了,更多可参见:System properties

0x4、Gradle基础

1. Gradle构建生命周期

Gradle构建分为三大阶段:

2. 生命周期监听(HOOK)

3. Grovvy基础语法速成

Grovvy是JVM上的 脚本语言,基于Java扩展的 动态语言,除了兼容Java外,还加入了闭包等新功能。

Gradle会把**.gradle** Groovy脚本编译成.class java字节码文件在JVM上运行。

Gradle是自动化构建工具,运行在JVM上的一个程序,Groovy是基于JVM的一种语言,他两间的关系就想Android和Java一样。

Gradle中涉及Groovy的语法只是都是比较简单的,学完对Groovy感兴趣可自行移步到官网学习(groovy API)。

Android项目采用Gradle构建,默认使用 Groovy DSL 脚本构建,从Gradle 4.0开始,正式支持 Kotlin DSL 脚本构建,两者可以共存,本节基于 Groovy DSL 进行讲解。(个人感觉他两语法实在是太像了,会Kotlin迁移到Groovy无压力~)

基础规则

  • 注释与Java一致,支持:// 或 /**/
  • 不以分号结尾;
  • 单引号字符串不会对$符号转义,双引号字符串可以使用字符串模板,三引号是带格式的字符串;
  • 方法括号可省略,可不写return,默认返回最后一行代码;
  • 代码块可以作为参数传递

定义 (使用def关键字定义)

// 定义变量:Groovy支持动态类型,定义时可不指定类型,会自行推导

def a = 1 // 定义整型,Groovy编译器会将所有基本类型都包装成对象类型
def b = “字符串:${a}” // 定义字符串模板
de double c = 1.0 // 定义Double类型

声明变量

// 局部变量,仅在声明它们的范围内可见
def dest = “dest”
task copy(type: Copy) {
from “source”
into dest
}

// ext额外属性,Gradle域模型中所有增强对象都可以容纳额外的用户定义属性
ext {
springVersion = “3.1.0.RELEASE”
emailNotification = “build@master.org”
}

task printProperties {
doLast {
println springVersion
println emailNotification
}
}

// 用类型修饰符声明的变量在闭包中可见,但在方法中不可见
String localScope1 = ‘localScope1’

println localScope1

closure = {
println localScope1
}

def method() {
try {
localScope1
} catch (MissingPropertyException e) {
println ‘localScope1NotAvailable’
}
}

closure.call()
method()

// 输出结果:
// localScope1
// localScope1
// localScope1NotAvailable

函数

// 无返回值的函数需使用def关键字,最后一行代码的执行结果就是返回值
// 无参函数
def fun1() { }

// 有参函数
def fun2(def1, def2) { }

// 指定了函数返回类型,则可不加def关键字
String fun3() { return “返回值” }

// 简化下,效果同fun3
String fun4() { “返回值” }

// 函数调用可以不加括号
println fun3

循环

// i前面b,输出5个测试
for(i = 0;i < 5;i++) {
println(“测试”)
}

// 输出6个测试
for(i in 0…5) {
println(“测试”)
}

// 如果想输出5个可改成:
for(i in 0…<5)

// 循环次数,从0循环到4
4.times{
println(“测试: ${it}”)
}

三目运算符、判断

// 和Java一致,判空还可以简写成这样:
def name = ‘d’
def result = name?: “abc”

// 还有用?判空,跟Kotlin的一样,person不为空 → Data属性不为空 → 才打印name
println person?.Data?.name

// asType是类型转换
def s3 = s1.asType(Integer)

闭包

闭包的本质就是 代码块,运行时可作为变量传递的函数,并保留定义它们的变量的范围的访问。

// 定义闭包
def clouser = { String param1, int param2 -> // 箭头前面是参数定义,后面是代码
println “代码部分”
}

// 调用闭包
clouser.call()
clouser()

// 闭包没定义参数的话,隐含一个it参数,和this作用类似
def noParamClosure = { it-> true }

// 函数最后一个参数都是一个闭包,可以省略圆括号,类似于回调函数的用法
task CoderPig {
doLast ({
println “Test”
})
}

task CoderPig {
doLast {
println “Test”
}
}

// 闭包里的关键变量,没有闭包嵌套时都指向同一个,有闭包时:
// this:闭包定义处的类;
// owner,delegate:离他最近的哪个闭包对象;

// 闭包委托:每个闭包都有一个delegate对象,Groovy使用该对象来查找
// 不是闭包的局部变量或参数的变量和方法引用,就是代理模式
class Info {
int id;
String code;

def log() {
println(“code: c o d e ; i d : {code};id: code;id:{id}”)
}
}

def info(Closure closure) {
Info p = new Info()
closure.delegate = p
// 委托模式优先
closure.setResolveStrategy(Closure.DELEGATE_FIRST)
closure§
}

task configClosure {
doLast {
info {
code = “cix”
id = 1
log()
}
}
}

// 输出:Task :configClosure
// code:cix;id:1

集合

// 数组,定义方式扩展如下,其他和Java类似
def array1 = [1, 2, 3, 4, 5] as int[]
int[] array2 = [1, 2, 3, 4, 5]

/* List:链表,对应ArrayList,变量由[]定义,元素可以是任何对象。*/

// 定义列表
def testList = [1, 2, 3]

// 添加元素,左移位添加新元素
testList << 300;
testList.add(6)
testList.leftShift(7)

// 删除
testList.remove(7)
testList.removeAt(7)
testList.removeElement(6)
testList.removeAll { return it % 2 == 0 } // 自定义规则

// 查找
int result = testList.find { return it % 2 == 0 }
def result2 = testList.findAll { return it % 2 != 0 }
def result3 = testList.any { return it % 2 != 0 }
def result4 = testList.every { return it % 2 == 0 }

// 获取最小值、最大值、满足条件的数量
list.min()
list.max(return Math.abs(it))
def num = findList.count { return it >= 2 }

//排序
testList.sort()
sortList.sort { a, b ->
a == b ?0 :
Math.abs(a) < Math.abs(b) ? 1 : -1
}

/* Map:键值表,对应LinkedHashMap,使用 : 冒号定义,key必须为字符串,可以不用引号包裹 */

// 存取
aMap.keyName
aMap[‘keyName’]
aMap.anotherkey = “i am map”
aMap.anotherkey = [a: 1, b: 2]

// 遍历
def result = “”
[a:1, b:2].each { key, value ->
result += “ k e y key keyvalue”
}
// 带索引遍历(从0开始的计数器,两个参数时传递的Map.Entry对象)
[a:1, b:2].eachWithIndex { entry,index, ->
result += “ e n t r y entry entryindex”
}

[a:1, b:2].eachWithIndex { key, value,index, ->
result += “ k e y key keyvalue$index”
}

// 分组
def group = students.groupBy { def student ->
return student.value.score >= 60 ? ‘及格’ : ‘不及格’
}

/* Range,范围,对List的一种扩展 */
def range = 1…5
println(range) //输出:[1, 2, 3, 4, 5]
range.size() // 长度
range.iterator() // 迭代器
def s1 = range.get(1) // 获取标号为1的元素
range.contains(5) // 是否包含元素5
range.last() // 最后一个元素
range.remove(1) // 移除标号为1的元素
range.clear() // 清空列表
println("第一个数据: "+range.from) //第一个数据
println("最后一个数据: "+range.to) //最后一个数据

4. Project(项目)

Gradle的构建由一个或多个Project组成,一个打印Project信息的示例如下(build.gradle),创建了两个子module:

// 配置信息
description(“一个测试项目”)
version(“v0.0.1”)
group(“Test”)

// 定义一个打印项目的方法
def printProject(pj) {
println(“===============”)
println(“获取项目信息:”)
println(“项目名:” + pj.name)
println(“路径:” + pj.path)
println(“项目说明:” + pj.description)
println(“包含构建脚本的目录:” + pj.projectDir)
println(“生成文件目录:” + pj.buildDir)
println(“属于哪个组:” + pj.group)
println(“版本:” + pj.version)
}

// 获取所有项目信息
def getAllProjectInfo() {
// 根项目
printProject(project)
// 所有子项目,调用getAllprojects()可获得所有项目,即包含根项目
this.getSubprojects().eachWithIndex { Project entry, int i ->
printProject(entry)
}
}

// 调用方法
getAllProjectInfo()

运行结果如下:

还可以对某个Project进行配置,如:

project(‘module1’) {
description(“子模块1号”)
version(“v0.0.1”)
group(“Test”)
}

更多API可进入Project类中自行查看:

5. 任务(Task)

创建任务

/* === ① 创建一个名为customTask1的Task,使用gradlew customTask1执行此Task === */
def customTask1 = task(“customTask1”)
customTask1.doFirst {
println “Task【${name}】 → 执行之前”
}

customTask1.doLast {
println “Task【${name}】 → 执行之后”
}

// 输出:> Task :customTask1
// Task【customTask1】 → 执行之前
// Task【customTask1】 → 执行之后

/* ========== ② Map方式仅限相关配置,如:创建时指定分组 ====== */
def customTask2 = task(group: ‘test’, “customTask2”)
customTask2.doLast {
println(“任务:” + name + " 属于分组:" + customTask2.group)
}

// 输出:> Task :customTask2
// 任务:customTask2 属于分组:test

/* ================= ③ 闭包方式实现 =================== */
task customTask3 {
group(“test”)
description(“任务名+闭包创建任务”)
doLast {
println(“任务:” + name + " 属于分组:" + customTask2.group)
}
}

// 输出:> Task :customTask3
// 任务:customTask3 属于分组:test

/* ======================= ④ 通过TaskContainer创建 ==================== */
tasks.create(“customTask4”) {
group(“test”)
description(“通过TaskContainer创建”)
doLast {
println(“任务:” + name + " 属于分组:" + customTask2.group)
}
}

// 输出:> Task :customTask4
// 任务:customTask4 属于分组:test

/* ==================== ⑤ 自定义Task =================== */
class CustomTask extends DefaultTask {
// TaskAction注解表示Task本身要执行的方法
@TaskAction
def doSomeThing() {
println(“执行一些操作”)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

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

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

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

七大模块学习资料:如NDK模块开发、Android框架体系架构…

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。

这份体系学习笔记,适应人群:
**第一,**学习知识比较碎片化,没有合理的学习路线与进阶方向。
**第二,**开发几年,不知道如何进阶更进一步,比较迷茫。
**第三,**到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。

由于文章内容比较多,篇幅不允许,部分未展示内容以截图方式展示 。

转存中…(img-dZ0FE6oe-1712035290688)]

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

[外链图片转存中…(img-RIj19fnf-1712035290689)]

七大模块学习资料:如NDK模块开发、Android框架体系架构…

[外链图片转存中…(img-ZGzKtdqm-1712035290689)]

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。

这份体系学习笔记,适应人群:
**第一,**学习知识比较碎片化,没有合理的学习路线与进阶方向。
**第二,**开发几年,不知道如何进阶更进一步,比较迷茫。
**第三,**到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。

由于文章内容比较多,篇幅不允许,部分未展示内容以截图方式展示 。

本文已被CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值