Gradle Plugin入门使用

一、学习目标

  • 1、 了解 Gradle Plugin 的作用是什么?
  • 2、 如何去定义一个 Gradle Plugin?
  • 3、 自定义插件扩展Extension。

一、Gradle Plugin 的作用是什么?

  • 模块化构建脚本的功能
  • 公共的功能可以抽取出来成为插件,可以供多个 build.gradle 使用,增加复用性。

二、定义一个 Gradle Plugin

2.1、插件的处理和应用

为了将构建脚本的逻辑封装到插件中,Gradle 需要做以下两件事:处理插件应用插件到目标中

  • 处理插件

Gradle 会自动找到插件所在的位置,例如一个 buildSrc 名字 module 就会 Gradle 识别为插件工程。

  • 应用插件

一旦插件被应用到执行的构建脚本中,那么插件对应的 apply(T target) 方法就会被调用。

2.2、 Gradle Plugin 创建

将插件定义在 buildSrc 中,这里的 buildSrc 就是当前工程下的一个 module ,Gradle 规定当一个module被命名为 buildSrc 时就会被当成插件去处理。

按照以下的步骤来创建一个简单的插件工程吧:

  • 1、在当前工程下创建一个 Java Library 的 module,起名字为 buildSrc

  • 2、将 main/src/java 修改为 main/src/groovy


    项目结构
  • 3、创建类PluginTest实现 Plugin 接口并覆写 apply(T garget) 接口

Plugin<T> 是一个泛型接口,在定义插件是应该将这个泛型填为 Project 即可。

class PluginTest implements Plugin<Project> {

    @Override
    void apply(Project project) {
        //定义一个 Task 
        project.task("MyTask") {
            doLast {
                println "MyTask doLast invoke..."
            }
        }
    }
}
  • 4、在外部应用这个插件
//在 app 下的 build.gradle 引用这个插件
apply plugin: PluginTest
  • 5、验证效果

app module 引用了这个 PluginTest 插件,因此 app 这个 project 就有 MyTask 这个任务了,我们来执行一下验证一下效果吧。

./gradlew :app:MyTask      

好了,通过上面几个步骤,就可以创建一个简单的 Gradle Plugin 工程了,但是回想一下,我们新建一个工程之后,在 build.gradle 中,Gradle 会帮我们引用 Android 插件apply plugin: 'com.android.application',它们引用方式就跟我们上面引用方式是不一样哦。

那这种引用方式是怎么定义的呢?

这里其实是给我们的 Plugin 起了个别名,然后在外部就是用这个别名来引用。接下来我们通过源码来看看'com.android.application'`是怎么定义的?

【举例】Gradle Android Plugin 中定义了一个叫 AppPlugin 的插件,这个插件是 Gradle 插件对 Android 的扩展,内部定义 Android 相关的一些东西,例如 我们所熟知 android{} 内部的东西都是属于 Gradle 插件对 Android 的扩展。详细的内容可以参考另一篇博客:从源码角度分析 Gradle 插件对 Android 的扩展

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.plugin"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        multiDexEnabled true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

而这个 AppPlugin 就是 build.gradle 引入 apply plugin: 'com.android.application',查看源码,这个别名是定义在一个文件名上的,文件内容对这个 AppPlugin 的映射关系。

AppPlugin 别名

那么我们依样画葫芦,我们也来定义一下我们插件的别名吧:

下面来看一下如何来声明我们自己的 Plugin ID 的

  • 1、如下图所示在 src/main/resources/META-INF.gradle-plugins文件夹下创建文件

因为插件类的包名为 com.example.buildsrc ,所以该文件明就是 包名.properties

buildSrc结构
  • 2、文件内容

文件内容的 implementation-class 对应的值为插件类的全限名称

implementation-class=com.example.buildsrc.PluginTest
  • 3、引用插件

在 app 下的 build.gradle 引用这个插件

apply plugin:'com.example.buildsrc'
  • 4、验证效果

app module 引用了这个 PluginTest 插件,因此 app 这个 project 就有 MyTask 这个任务了,我们来执行一下验证一下效果吧。

./gradlew :app:MyTask      

好了,就这样,我们也可以像引用 Android Gradle Plugin ID 一样来引用我们自己的插件咯。

三、插件扩展 Extension

什么是扩展插件?

扩展插件 Extension 就是用于 Plugin 与 Project 通讯用的。

【举例】我们想在 build.gradle 中通过配置 Extension 相关的属性 ,然后将 Extension 这个对象传递给我们自定义的 Plugin。

下面我们还是基于 PluginTest 这个插件来定义一个简单的插件扩展。

  • 1、定义 TestExtension

我这里定义的是 Groovy Bean(跟 Java Bean 类似),内部定义一个 message 变量。

class TestExtension {
    String message;
}
  • 2、 将 TestExtension 添加到 project#extensions 集合中。
class TestPlugin implements Plugin<Project> {

    @Override
    void apply(Project project) {

        //TestExtension extension = project.getExtensions().create("testExt", TestExtension)
        //1.添加插件扩展到project.extensions集合中
        project.extensions.add("testExt", TestExtension)
        project.task("TestTask") {
            doLast {
                //2.获取外界配置的 TestExtension
                TestExtension extension = project.testExt
                //3.输出插件扩展属性
                println ">>>>>>" + extension.message
            }
        }
    }
}
  • 3、 给插件扩展属性赋值

//build.gradle

//依赖我们定义的插件
apply plugin: 'com.example.plugin.extension'
testExt {
    //给插件扩展的属性赋值
    message  "helloworld"
}
  • 4、 测试验证
./gradlew :app:TestTask

> Task :app:TestTask 
当前执行的 Task TestTask
>>>>>>helloworld

插件扩展在 Project 和 Plugin 之前传递数据如图所示

插件扩展

# 参考

记录于 2019年2月23日

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342