Android 中 gradle 之 groovy

Aandroid Studio 中使用 gradle 来管理一些信息,最早接触时感觉挺麻烦的,后来才逐渐感觉到它的厉害之处。前几年项目中接入了热修复 Tinker,我看了看它的源码,更感觉到脚本的厉害,还能动态的往 AndroidManifest 中添加一些信息,比如   等,我就好奇了,决定研究一下 groovy。看别的资料说它和 Java 很类似,能在 AS 中直接运行,那我就开始写 Demo。


首先创建个项目,然后创建个 module,我用的是 Java Library,此时我们可以直接书写 java 文件的代码了,但如果想写 groovy 文件,怎么办?直接创建文件肯定会失败,根本创建不出来。此时,得修改 module 中的 gradle 配置文件,

原版:

apply plugin: 'java-library'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}

sourceCompatibility = "1.7"
targetCompatibility = "1.7"


修改后:

apply plugin: 'groovy'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation gradleApi()
    implementation localGroovy()

}


此时,apply plugin: 'groovy' 会引入 groovy 插件,implementation localGroovy() 导入 Groovy 的库。然后删除 main 里面的所有文件夹,创建新的 groovy 文件夹,此时,点击鼠标右键 file,输入 MyGroovy.groovy ,点击OK,会出现一个空白文本,在里面写 

class MyGroovy {

}

这时候文本就会自动变为 groovy 格式,我们就可以在里面写代码了。注意,此时,需要在 gradle 中再添加些配置才能编译,新增内容如下:

 

task renameGroovyToJava {
    doLast {
        delete "$buildDir/classes/java"
        File file = new File("$buildDir/classes/groovy")
        // file.name = "java" 不行,会报错
        println file.renameTo("$buildDir/classes/java")
    }
}

compileJava.finalizedBy compileGroovy
compileGroovy.finalizedBy renameGroovyToJava

sourceSets {
    main {
        groovy {
            srcDir 'src/main/groovy'
        }

        resources {
            srcDir 'src/main/resources'
        }
    }
}


groovy 有两种写法,一种是 java 版,一种是脚本本。上面配置的这种是 java 版,在 gradle 中的写法是脚本版,不论是哪种方式,groovy 的语法是相同的。以 java 版为例,写个 main 入口, 打印个值

class MyGroovy {
    static void main(String[] args){
        println (" hello world ")
        println " hello world   args.length : ${args.length} "
    }
}

打印结果:

 hello world
 hello world   args.length : 0

在 groovy 中,打印时 println,可以带 (),也可以不带。 字符串中如果有引用,则使用 $ 或 ${} 来修饰。这点与 kotlin 一样,接下来好些东西都与 java 和 kotlin 一样,所以说,有 java 和 kotlin 基础,学起 groovy 特别快。


groovy 中的对象类型可以使用 def 来修饰,同样可以引用不用的类型,并且它有个闭包的概念,可以在方法内部用 it 来特指形参,比如

    static void main(String[] args){
        def va = 5
        va = [a: 1, b: 2, c: 3]
        va.each {it->
            println(it.key +"  " + it.value)
        }
    }

va 一开始指向的是 int 类型,接下来切换为 Map 类型,然后遍历,it 此时指的就是 Map 中的对象。也就是说,我们自定义了形参 it 来标识遍历的对象。


比如说IO流写入文本,或从文本中读取内容,groovy 也比较简单,如下

    static void main(String[] args){
        def file1 = new File("E:/a.txt")
        file1.withWriter("utf-8") {
            writer -> writer.writeLine(" hello world  \n  Death")
        }
        file1.eachLine {str->
            println(str)
        }
    }

此时会在电脑的 E 盘创建一个文本,里面就是我们写进去的内容。控制台也会有日志打印,证明写和读都成功。


groovy 最主要的一个特点就是闭包,那么我们自定义个方法看看什么是闭包,如下

    static void main(String[] args){
        def d = appStr.call("this is string",100)
        println(d)
    }

    static def appStr = { String param1, int param2 ->  //箭头前面是形参,箭头后面是代码
            println "this is code  $param1   $param2"  //这是代码
        return "return : this is code  $param1   $param2" //是返回值
    }

打印日志为:

this is code  this is string   100
return : this is code  this is string   100

这样就比较清楚的标明了什么是闭包。 AS 中的gradle脚本配置中,尤其是配置打出包的地址时,就会用到闭包。


回到一开始的疑问,gradle 中是如何往配置清单中添加节点信息的?我们先看个案例,如果获取节点信息的

    @TaskAction
    def function() {
        //获取到当前的manifest读取到的XmlSlurper中的读取结果
        def gpathResult = new XmlSlurper().parse(new File("app/src/main/AndroidManifest.xml"))
        //添加android对应的命名空间
        gpathResult.declareNamespace('android': 'http://schemas.android.com/apk/res/android')
        //读取meta-data示例
        for (metaData in gpathResult.application.'meta-data'){
            println "name=="+ metaData.@'android:name' + "  value=="+metaData.@'android:value'
        }
    }

这样,它会把自定目录下的配置清单里的 meta-data 节点内容都读取出来。

你可能感兴趣的:(Android,知识)