Gradle Kotlin DSL , 你知道它吗?
Posted 刘某人程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gradle Kotlin DSL , 你知道它吗?相关的知识,希望对你有一定的参考价值。
一.前言
kotlin我相信大家实际上还是挺熟悉的,哪怕不熟悉,也没有关系,它跟Java是百分百兼容的,很多的语法是有点类似的,所以只要有Java基础,学习Kotlin并不是什么难事,再加上现在kotlin大热,Google多次在各种大会上力推,如果这个时候我们掌握了kotlin,肯定能给我们提升很大的帮助。
而且Kotlin本身就是一门让人爱不释手的语言,写起来还是很赞的,不管你需不需要学习,进来看看,开阔下视野总是没错的。
自Kotlin被Google转正之后,这门语言就备受我们Android开发者的关注,经过几年的发展下来,Kotlin俨然已经成为了一门出色的开发语言,它人性化的语法以及语法糖都深受人们的喜爱,再加上这几年来AI概念的大热,让越来越多的开发者正襟危坐,如何提高自身的竞争力?如何提高自身的技术栈?这成了大部分初中级开发者的第一个难关,而在另一大领域物联网行业中风生水起的语音控制,也逐渐开始崭露头角,如百度小度,小米小爱,天猫精灵等,那么如果Kotlin + AI + 语音控制,会碰撞出什么火花来呢?
在我的新课程中,就使用到了此技术,并且辅以组件化的架构,有兴趣可以了解一下
二.Gradle Kotlin DSL入门
总所周知,我们现在android Studio是使用Gradle来编译,而默认的构建语言是Groovy,但是Gradle实际上是支持Kotlin来编写Gradle构建脚本的,常见的构建脚本是.gradle结尾,而Koltin语法编写的脚本则是.gradle.kts,今天就带大家来尝试一下,而Gradle官网也是给出了Groovy迁移Kotlin的指导文章,有兴趣也可以看下
Migrating build logic from Groovy to Kotlin
Gradle的Kotlin DSL提供了传统Groovy DSL的替代语法,并在受支持的IDE中提供了增强的编辑体验,并具有出色的内容辅助,重构,文档等功能,这是官方给出的一些定义,当然,他也是有限制的,所以尽可能的保证Gradle和Android版本为最新版本是很有必要的,当然,JDK的版本至少是在8或者以上,有了这些铺垫之后,我们就可以开始着手来改造一个项目了
三.Gradle脚本改造
我们先区分一些语法的不同
- 1.Groovy字符串可以用单引号’string’或双引号引起来"string",而Kotlin需要双引号"string"。
- 2.Groovy允许在调用函数时省略括号,而Kotlin始终需要括号。
- 3.Gradle Groovy DSL允许=在分配属性时省略赋值运算符,而Kotlin始终需要赋值运算符。
然后我们要知道,一个基于Gradle构建的项目,默认会有哪些配置文件?
- settings.gradle
- project/build.gradle
- app/build.gradle
无外乎这三个配置,那么我们现在就开始来改造吧。
1.settings.gradle
在我们项目的根目录下,有一个settings.gradle这样的文件,它主要是负责我们项目的Model声明,那么我们首先先重名名一下文件名,增加.kts的后缀,如图,连图标都变了
那么我们内部的代码应该如何重写?先来看下原先的代码
include ':app'
rootProject.name = "KotlinDSL"
这段代码很简单,就是声明了app这个主Module,同时定义了我们project的名称,我们可以通过kotlin的语法进行改写:
为了便于阅读,这里我直接截图显示,可以看到这里我们遵循了刚才的注意事项,把app的单引号变成了双引号,然后等于号修改成了括号,来看下源码
再来看下Groovy中的源码:
你会发现,其实语法差不多,但是要注意我们刚才上面的提示信息:
Gradle Groovy DSL允许=在分配属性时省略赋值运算符,而Kotlin始终需要赋值运算符。
有了这一层的说明,大家就明白什么意思了,那么懂了这些基本知识之后,我们就可以来晚一些大的了。
2.project/build.gradle
那么我们应该如何来处理呢?我们先把它的后缀改了
改完了之后,我们就要来看里边的代码了
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript
ext.kotlin_version = "1.3.72"
repositories
google()
jcenter()
dependencies
classpath "com.android.tools.build:gradle:4.0.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
allprojects
repositories
google()
jcenter()
task clean(type: Delete)
delete rootProject.buildDir
改造第一步,就是我们的classpath了,那么在Groovy中,我们有一个ext的扩展,但是在kt中实际上是没有的,所以我们只能自己先声明一个局部变量了,另外就是classpath引入的全局依赖,我们还是要用大括号括起来,其他倒是不需要改变,但是可以看到,还有一个clean的任务,这个也是需要重写的,我们可以看到它是利用Delete中的delete函数来删除我们的build文件夹,这就好办了,直接改下即可,来看下截图
IDE还是非常的友好的,一些基本的提示都是有的
当儿,我们也可以简化依赖的操作,就拿kotlin插件来说吧,它最长了,我们可以声明一下
可以看到,classpath是支持kotlin函数的,我们只要传入module的名称和版本号即可,所以这样写是不是非常的美观呢?
当然,这些都是小儿科,我们再来改造下内容比较多的app下build.gradle
3.app/build.gradle
先把后缀改了,这都是老生常谈了,至此我们的工程配置到了最后一步了,但是我们要走的路还很远
这里面的内容很多,我就不贴代码了,而是分模块给大家理清楚逻辑,先把最基本的单引号改成双引号,接着把等号的函数调用全部改成括号,然后接着往下看
插件的引入
Groovy的插件引入是这样的
apply plugin : 'com.android.application'
apply plugin : 'kotlin-android'
apply plugin : 'kotlin-android-extensions'
我们可以简化成这样
SDK引入
而SDK的引入如下
compileSdkVersion 29
buildToolsVersion "29.0.3"
我们可以改成这样
默认配置
默认配置是这样
defaultConfig
applicationId "com.liuguilin.kotlindsl"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
我们可以改成这样
这里要注意的是,像minSdkVersion,targetSdkVersion这种实际上是一个函数,我们来看源码
所以我们要加括号,因为Groovy是省略了括号的,而像versionCode,versionName这些,实际上是变量,我们我们用等于号赋值
如果不明白这些参数和函数的意义,不妨大胆的阅读源码。
编译类型
编译类型是这样的
buildTypes
release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
我们可以改成这样
可以看到我们通过getByName来获取编译类型,并且可以获取debug的编译类型或者自定义的编译类型
依赖的添加
依赖这块可以看到Govvey是这样的
dependencies
implementation fileTree (dir: "libs", include: ["*.jar"])
implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.3.72'
implementation 'androidx.core:core-ktx:1.3.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
可以看到其他都没什么,就是这个fileTree我们要考虑下,在kotlin中使用冒号:来做键值对的,那就是map了,所以我们可以这样改造
至此呢,我们的基本改造算是完成了,能正常运行就表示一切正常了。
在我的新课中,我们从架构上开始入手,从零开始搭建一套以组件化为基础的应用框架,以Kotlin Gradle DSL为编译链脚本,AI语音为核心功能,从架构层次到应用层级再到具体功能落实,以清晰优雅的方式完成实战,提高自己的超前逻辑,向更高级别的工程师铺垫。
四.Gradle Kotlin DSL进阶
我们虽然是改造了脚本,但是该有的特性还是不能丢的,我们来开始完善
1.自动打包
使用Gradle自动打包,包括渠道等,都是太正常不过了,我们来改造下,先常规的生成一个签名吧:
我把签名放在main文件夹下的jks文件夹下
先来看下原生的自动打包是如何做的,首先定义签名配置
//签名配置
signingConfigs
release
//别名
keyAlias 'kotlin'
//别名密码
keyPassword '123456'
//路径
storeFile file('../app/src/main/jks/kotlin.jks')
//密码
storePassword '123456'
然后在编译类型中,release类型里引用即可
buildTypes
release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
//自动签名
signingConfig signingConfigs.release
那么我们现在用kotlin来改写吧:
差别不算太大,定义好签名配置之后,去引用下即可
这样我们就可以使用Gradle的命令打包了
打包成功之后就可以在app/build/output目录下找到对应编译类型的包了
当然,这个名字太难看了,我们每次发版本的时候还要自己去修改,那么我们来修改下名称
2.输出文件名称
Groovy的代码如下:
android.applicationVariants.all variant ->
def buildType = variant.buildType.name
def createTime = new Date().format("YYYY_MM_dd_HH_mm", TimeZone.getTimeZone("GMT+08:00"))
def fileName
variant.outputs.each
if (buildType == "release")
fileName = "DSL_V$defaultConfig.versionName_$createTime_$buildType.apk"
else if (buildType == "debug")
fileName = "DSL_V$defaultConfig.versionName_$buildType.apk"
it.outputFileName = fileName
那么我们优化下之后:
最终我们在output文件夹下就可以看到我们命名的应用了
至于时间的话,这个要在后面讲
3.指定JDK
我们如果想要使用Lambda表达式的话,需要指定JDK为8或者以上,而Groovy的代码如下:
//JDK8
compileOptions
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
那么在Kotlin中其实就是改成等号赋值即可
4.资源重定向
这个算是黑科技了,有没有发现我们的res/layout下,当项目庞大的时候,会出现很多的文件,这是不可避免的,但是我们可以用资源重定向的方式来给布局文件进行分类,效果如图
这样做的好处呢,首先是不会影响我们正常的使用,其次可以分类好我们的布局文件,那这样的效果需要怎么实现呢?
先来看下Groovy语言的实现
//资源重定向
def listSubFile =
//新资源目录
def resFolder = 'src/main/res/layouts'
//新资源目录下的文件夹
def files = file(resFolder).listFiles()
def folders = []
//遍历路径
files.each
item -> folders.add(item.absolutePath)
//资源整合
folders.add(file(resFolder).parentFile.absolutePath)
return folders
sourceSets
main
//重定向资源
res.srcDirs = listSubFile()
可以看到,定义了一个变量listSubFile去计算循环采集我们定义好的layouts,然后得到目录,再通过sourceSets重新定义资源文件即可。
如果我们用Kotlin DSL应该如何去写呢?
很简单,基本一致,定义一个方法返回list即可。
五.ext扩展函数的替代方式
我们在使用Groovy语言构建的时候,往往会抽取一个build_config.gradle来作为全局的变量控制,而ext扩展函数则是必须要使用到的,而在我们的Gradle Kotlin DSL中,如果想要使用全局控制,则需要buildSrc
复杂的构建逻辑通常很适合作为自定义任务或二进制插件进行封装。自定义任务和插件实现不应存在于构建脚本中。buildSrc则不需要在多个独立项目之间共享代码,就可以非常方便地使用该代码了。
buildSrc被视为构建目录。编译器发现目录后,Gradle会自动编译并测试此代码,并将其放入构建脚本的类路径中。
对于多项目构建,只能有一个buildSrc目录,该目录必须位于根项目目录中。
那么我们来开始写吧。
首先创建一个buildSrc的文件夹,然后创建一系列目录,如图
其中test目录是可以不用创建的,创建好之后使用Gradle Sync下,然后就可以看到如下目录
这里要注意的是,src目录要按照我截图的方式来创建,然后来编辑settings.gradle.kts
rootProject.buildFileName = "build.gradle.kts"
这里我就指定了一下编译文件是build.gradle.kts,再来编辑下这个文件
按照官方文档的引导,我们写完编译脚本后就可以执行gradle init来编译了,编译成功之后我们就可以快乐的玩耍了
1.输入APK增加编译时间
在上文中我们有讲到如果修改输出的APK名称,但是我们每次编译出来最好增加个时间好做版本管理和历史版本归档,那么我们可以在APK名称上增加事件了,而在Groovy语言中可以直接使用java的代码获取到时间,而在我们的DSL中,我们可以在刚才的buildSrc中定义方法
我定义了一个获取时间的方法后,在build.gradle.kts中可以这样去修改
然后执行编译命令
最终我们可以看到,release版本增加了时间,是不是很nice,我们可以继续去抽取和封装
2.版本和依赖管理
我把所有的依赖都抽取了出来,可以看下截图
版本,插件,SDK版本以及依赖都可以在这个目录进行更新,方便管理,那么外部的调用情况如何呢?
先来看下project中的build.gradle.kts
这样调用即可,再来看下app的build.gradle.kts
这是配置
这是依赖
至此,你就完全学会了Gradle Kotlin DSL的技巧了。
掌握组件化架构及AI语音的基本组成和使用,多个应用场景提高技术栈,更加深刻的理解Kotlin语言。
课程整体分为四大部分,第一部分着重讲解了Kotlin Gradle DSL的脚本编写,第二部分着重讲解了组件化架构项目的实施,第三部分着重讲解了AI人工智能语音的实现,第四部分则完善语义的场景,让交互更加人性化。
六.源码下载
链接:https://pan.baidu.com/s/1VresQSufixht5DbnW4FrVw
提取码:kxwj
以上是关于Gradle Kotlin DSL , 你知道它吗?的主要内容,如果未能解决你的问题,请参考以下文章
Gradle Kotlin DSL 的 accessors 生成问题
Gradle Kotlin DSL:在独特的地方定义 Kotlin 版本
如何从非 build-gradle 文件访问 Kotlin DSL 扩展?