阅读 136

gradle之:自定义插件

一.自定义插件(plugin)的目的

插件是一个gradle的扩展,这里思考一个问题,有了task之后,为什么还需要自定义插件?

这里我认为自定义插件是为了组合一系列task,提供更高颗粒度的复用能力。

并且gradle plugin还可以包在jar包或者aar中发布到远程仓库

二.自定义插件的步骤

2.1 自定义插件的方式

新建plugin的模块有两种方式,独立发布插件和简化插件。

  • 简化插件的定义利用了gradle自动识别buildSrc目录的特征,将自定义插件放置到buildSrc目录下,它的缺点是无法发布到远程被复用。

  • 独立发布插件方式步骤与简化方式基本一致,但是可以发布到远程maven仓库

2.1.1 简化方式定义插件

新建一个文件夹命名为buildSrc,同时在这个目录下新建build.gradle,注意名字和大小写必须完全一致,gradle在启动时会在配置阶段自动扫描buildSrc目录,并配置buildSrc下的build.gradle。

在buildSrc下新建两个目录

  • src/main/groovy

  • src/main/java

然后在build.gradle中添加对应的plugin插件

buildscript {

    repositories {
        google()
        jcenter()
        mavenCentral()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.2'
    }
}

//识别groovy 插件
apply plugin : "groovy"
apply plugin: "java"

repositories {
    mavenCentral()
}

dependencies {

}复制代码

其中:

apply plugin : "groovy"
apply plugin: "java"复制代码

当添加这两行后,你会发现android studio会将groovy目录和java目录转变成蓝色表示已经识别到了,也可以只添加一种比如groovy或者java目录,这样,我们实现插件的语言就根据自己选择的plugin转换,一般建议用groovy更加高效简洁。

2.1.1 独立发布方式定义插件

新建一个java模块,命名为plugins,同样新建目录src/main/groovy,名字不需要固定,在plugins目录下添加build.gradle,

plugins {
    id 'groovy'
}

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

    //我们需要实现gradle的Plugin<T>接口,来做自定义插件,因此依赖gradle api
    implementation gradleApi()
    //依赖gradle提供的groovy sdk,在编写自定义插件的时候,用groovy更快。
    implementation localGroovy()
}复制代码

这里与简化方式的区别在于需要在dependencies下添加依赖

implementation gradleApi()
implementation localGroovy()复制代码

2.2 申明配置plugin

这个步骤作用在于申明定义的plugin的名字,方便我们依赖插件。

在src目录下新建resources/META-INF/gradle-plugins目录,在这个目录下新建xxx.xxx.xxx.properties文件,这个xxx,代表的是不包含类名的插件的完整包路径,如com.hch.bsDiff下的BsDiffPlugin,我们生成的properties文件为com.hchbsDiff.properties,里面的内容为

implementation-class=com.hch.plugin.BsDiffPlugin复制代码

2.3 自定义plugin

自定义plugin是真正做事的地方,一般一个plugin与一个任务对应,通过继承自plugin来定义一个插件

class BsDiffPlugin implements Plugin<Project>{

    @Override
    void apply(Project project) {
        project.afterEvaluate {
            //只是定义任务,不会执行,执行还需要手动 ./gradlew bsDiff
            project.task(type:BsDiffTask , "bsDiff"){
                inputs.files "${project.rootDir.absolutePath}/temp/testold.txt","${project.rootDir.absolutePath}/temp/testnew.txt"
                outputs.files "${project.rootDir.absolutePath}/temp/testdiff.patch"
            }
        }
    }
}复制代码

在gradle的配置阶段,plugin的apply方法会被执行,一般在这个方法里面,我们会关联一个task,并将关联的task的参数传递进去,通过project参数,我们能拿到与构建流程相关的所有信息。

这里我们定义了一个BsDiffPlugin插件,同时生成一个bsDiffTask。

2.4 定义插件关联的任务

BsDiffTask

class BsDiffTask extends DefaultTask{


    //外部生成任务的时候,会修改 project.task(type:com.hch.plugin.BsDiffTask , "bsDiffWrapper")
    BsDiffTask(){
        group "差分任务"
        description "bsDiff"
    }

    @TaskAction
    void diff(){
        println "start diff...."
        File fileOld = inputs.files.files[0];
        File fileNew = inputs.files.files[1];
        File diff = outputs.files.files[0];
        BSDiff.bsdiff(fileOld , fileNew , diff);
        println "end diff...."
    }
}复制代码

2.5 使用自定义的插件

2.5.1 简化插件依赖

如果是简化插件,我们仅需要在项目app中的build.gradle中通过两种方式使用自定义插件

//方式一
plugins{
    id 'com.hch.plugin.bsDiff'
}

//方式二
apply plugin: BsDiffPlugin复制代码

这里的id就是properties的名字

2.5.2 独立插件依赖

如果是独立的插件,还需要添加plugin的依赖

在根目录的build.gradle中添加

buildscript{
    repositories{
        //...

        //指定一个maven仓库的路径
        maven {
            url "xxxxx"
        }
    }
    dependencies{
        //...
        
        classpath('com.hch.bsdiff:BsDiffPlugin')
    }
}复制代码

同时也需要在app下的build.gradle中增加

//方式一
plugins{
    id 'com.hch.plugin.bsDiff'
}

//方式二
apply plugin: BsDiffPlugin复制代码

2.5.3 使用插件中的任务

插件被依赖到项目中后,我们就可以使用插件中的任务了

afterEvaluate {
    println "assembleRelease === ${assembleRelease}"
    assembleRelease.finalizedBy 'bsDiff'
}


作者:八道
链接:https://juejin.cn/post/7021729648480354311


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐