学习Android Gradle
前言
之前工作,在使用Android gradle时翻过车,因此对其产生了浓重的好奇感。买了本《Android Gradle 权威指南》,进一步学习一下。书很薄,200多页。这对一个没有很好看书习惯的我来说,是一件好事。开撸的时候就遇到了一个坎,不能理解“闭包”的概念。我尝试忽略这个概念继续读下去,可是发现,这是一个重要的感念,贯通全书,于是开始研究“闭包”。这期间发现闭包很像android中使用过的Lambda。当搞清楚闭包的概念之后,再读本书就轻松多了。
本书算是读了两遍,第一遍有些不理解的,在第二次阅读时清晰了很多。今天是读第二遍结束的日子。留下笔记,来纪念这为数不多的通读的书籍的伟大时刻。
这里印象最深的除了那个坎,还有就是以前使用过的技术点。之前只是使用,现在了解了原理。个人认为,看书,对于新的技术点,做个了解,当用到的时候可以有个大致的概念,具体怎么用,现查资料就好了。
历程
最早:.gradle破玩意,弄不好工程就跑不来。新建工程,再有就是,从Eclipse拉个工程到android studio中,编译不过的原因经常是因为gradle没配置好,当时最好的办法就是,去可以编译过的工程中复制gradle的内容。
成长:熟悉gradle的依赖项配置
成长:定制系统多应用联合开发,由于架构要求,多模块联合开发。开始重视gradle的使用。开始配置本地依赖项,服务端依赖项。头疼的事情又来了,依赖冲突,头都大了。
成长:项目变更,重新审视gradle。增加各个模块gradle的统一配置文件。开始使用命令行运行gradle。
当前:阅读书籍,加深gradle的使用方式以及原理。
经验
gradle看似无关紧要的东西,随便上网上找点配置信息,删删减减编译过就行了,可能后期就再也用不上了。哪怕你多引了些依赖,都不会有太大的影响。
但是,项目大了后,对于协同开发,base代码引用,新人接手代码来说,一个很烂的gradle会带来很多麻烦。
开发过程中遇到最大的问题,就是版本冲突,有时就是毫无头绪的冲突。对于不熟悉gradle的人来说,事件很头疼的事,哪怕你对代码组织结构很了解。使用gradle命令行(android stdio有可视化的gradle使用方式),就会相对简单的解决冲突问题。可以查看项目的依赖树,如果这是一颗大树,也够你头疼一阵的,不过怎么也比没有头绪要强。
推荐一个比较万能的方法,会解决很多开发过程中遇到的编译问题,就是:gradlew assembleDebug 。
收获
《Android Gradle 权威指南》这本书前面介绍了些gradle的基本概念以及使用方法。
含闭包代码的演变过程
def numList= [1,2,3,4,5,6,7,8]
// 原始写法,接受一个闭包作为参数,each源码处可以接收一个闭包参数
numList.each({println it})
// 重新布局
numList.each({
println it
})
// 语法规则,最后一个参数是闭包,可以放到方法的大括号里。
numList.each(){
println it
}
// 语法规则,可以生活方法的小括号
numList.each{
println it
}
// 以上就是我们常见的格式了
几个重要文件
settings.gradle文件:
这个文件可配置编译器当前可以显示的模块,一般是一个application和多个library模块
这里遇到过的问题
1 使用相对路径,可能出现引用不到对应的模块的情况。以settings.gradle所在目录为基准。
2 最好清理掉不再引用的模块,工程就少一点冗余
3 如果将模块作为aar包提交到服务端,然后项目对aar进行引用,注意给引用价格标志位。可以灵活切换aar包与源码的引用
build.gradle文件:
主要分为两种
一种是全局的build.gradle:
配置项目内所有gradle的公共属性,常见的服务端代码库的引用
另一种是个模块的build.gradle
重头戏,各模块的主要配置就在这里
apply plugin: 'maven' // 应用二进制插件
apply from: '../../**.gradle' // 引用脚本插件,新建gradle文件,可写方法,可设置gradle全局属性,使用:引用依赖的版本号可以在这里配置
使用中…
1 多项目统一配置:
统一配置信息,可单独建立***.gradle文件,对公共属性进行定义,各项目在build.gradle中引入该***.gradle文件,引用方式为apply from: '***.gradle'(可以是相对路径,也可以是绝对路径,建议使用相对路径)。这样各项目就可以统一配置对应信息,比如minSdkVersion、versionName...等属性。
2 gradle指定属性:
在使用gradle编译apk时,可通过-P+指定属性的方式,为gradle设置指定属性内容。同上面建立***.gradle功能类似,为gradle设置属性。在使用命令行编译apk是,用来配置apk输入目录与apk名很方便。
“build.gradle”
applicationVariants.all {variant ->
variant.outputs.all {output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
if (variant.buildType.name == "release") {
if(project.hasProperty('APK_NAME') && project.hasProperty('APK_PATH')){
// 设置apk名
outputFileName = new File("${APK_NAME}")
// 更改输出路径
variant.getPackageApplication().outputDirectory = new File("${APK_PATH}")
}
}
}
}
}
命令行:-P是指定属性的前缀,注意-P与属性之间没有空格
gradle assembleRelease -PAPK_PATH=D:/ -PAPK_NAME=test.apk
3 多工程联合开发
开发到一定阶段后,会涉及到项目整合,那这时出现最大的问题就是引包冲突。这是个棘手的问题,写到这,之前的经历历历在目,煎熬与无奈。
后来发现,结合着gradle使用,会将问题变得简单些:
使用gradle assembleDebug 编译apk,这时会报错,那么就这报错的点(其实是在gradle编译过程中,会阻塞到某个gradle方法)继续使用gradle,通过gradle + 阻塞的点 + --stacktrace,就会找到异常点,根据这个异常点或多或少能找到冲突点。
4 windows与linux区别
windows上使用gradlew来执行gradle脚本
linux上使用gradle来执行gradle脚本
在使用task buildApk(type:Exec)自定义gradle task时(使用gradle执行命令行),
windows上使用commandLine 'cmd', '/c', “命令”
linux上使用gcommandLine 'sh', '-c', “命令”