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

简介: 系统学习下Gradle吧,希望对想学Gradle的朋友有所裨益。

6. 包都下到哪里去了


问题来了:下载的第三方依赖库都放哪里去了


答:~/.gradle/cache/dodules-2/files-2.1/包名/库名/版本号/hash字符串/,示例如下:


网络异常,图片无法展示
|


如果你不想将gradle相关的下到~/.gradle下,可自行添加环境变量

GRADLE_USER_HOME,如:


网络异常,图片无法展示
|


后续,gradle下载的东西就会放到这个目录下了:


网络异常,图片无法展示
|


上述改动,在Android Studio不一定会生效哦,有时还需自行配置:


网络异常,图片无法展示
|


0x2、Gradle的执行架构


当我想删除上面这个C:\Test的目录时,却发现删除不了:


网络异常,图片无法展示
|


就是有进程在占用这个文件夹,那是什么进程呢?答:daemon进程,可以键入下述命令 gradle --status 查看一波:


网络异常,图片无法展示
|


进程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:${code};id:${id}")
    }
}
def info(Closure<Info> closure) {
    Info p = new Info()
    closure.delegate = p
    // 委托模式优先
    closure.setResolveStrategy(Closure.DELEGATE_FIRST)
    closure(p)
}
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 += "$key$value" 
}
// 带索引遍历(从0开始的计数器,两个参数时传递的Map.Entry对象)
[a:1, b:2].eachWithIndex { entry,index, -> 
    result += "$entry$index" 
}
[a:1, b:2].eachWithIndex  { key, value,index, -> 
    result += "$key$value$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月前
|
缓存 Unix Android开发
Android安卓项目调试之Gradle 与 Gradle Wrapper的概念以及常用gradle命令深度详解-优雅草卓伊凡
Android安卓项目调试之Gradle 与 Gradle Wrapper的概念以及常用gradle命令深度详解-优雅草卓伊凡
420 8
|
4月前
|
存储 API Android开发
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
244 4
【02】完整的安卓二次商业实战-配置gradle-构建打包原生安卓项目-调试本地运行模拟器-优雅草伊凡
|
4月前
|
Java 开发工具 Maven
【01】完整的安卓二次商业实战-详细的初级步骤同步项目和gradle配置以及开发思路-优雅草伊凡
【01】完整的安卓二次商业实战-详细的初级步骤同步项目和gradle配置以及开发思路-优雅草伊凡
299 6
|
8月前
|
Java Android开发
Android studio中build.gradle文件简单介绍
本文解析了Android项目中build.gradle文件的作用,包括jcenter仓库配置、模块类型定义、包名设置及依赖管理,涵盖本地、库和远程依赖的区别。
759 19
|
Android开发
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
Android基于gradle task检查各个module之间资源文件冲突情况
|
11月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
784 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
11月前
|
缓存 Java 测试技术
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
1615 3
【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
|
Android开发
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
Android gradle task任务检查各个module之间资源文件冲突.md
|
Java Android开发 Windows
玩转安卓之配置gradle-8.2.1
为安卓开发配置Gradle 8.2.1,包括下载和解压Gradle、配置环境变量、修改配置文件以增加国内镜像,以及在Android Studio中配置Gradle和JDK的过程。
1557 0
玩转安卓之配置gradle-8.2.1
|
Android开发
Android Studio: 解决Gradle sync failed 错误
本文介绍了解决Android Studio中出现的Gradle同步失败错误的步骤,包括从`gradle-wrapper.properties`文件中获取Gradle的下载链接,手动下载Gradle压缩包,并替换默认下载路径中的临时文件,然后重新触发Android Studio的"Try Again"来完成同步。
8198 0
Android Studio: 解决Gradle sync failed 错误

热门文章

最新文章

推荐镜像

更多