聊聊Gradle插件

栏目: Groovy · 发布时间: 4年前

内容简介:相信作为一个Android开发者,对Gradle这个强大的构建工具一定不陌生。Gradle插件是Gradle作为优秀的构建工具很大的一个特点。在Android中不同的模块下看到的现在执行下面命令:hello.gradle的内容:

相信作为一个Android开发者,对Gradle这个强大的构建 工具 一定不陌生。Gradle插件是Gradle作为优秀的构建工具很大的一个特点。在Android中不同的模块下看到的 apply plugin:xxx 表达式就是插件的使用。一直都是使用别人的插件,今天我们就自己动手来实现一下简单的插件。

为什么要使用Gradle插件?

Gradle插件主要的作用是可以实现代码的构建代码的重用。

脚本插件和对象插件

  • 脚本插件就是通过把重用的构建逻辑 单独写一个gradle文件 中实现重用。

  • 对象插件则是通过实现 org.gradle.api.Plugin 来插件的编写。严格意思上来说,这个才能叫真正的插件,前面方式只能叫做一种逻辑的封装。

脚本插件

现在执行下面命令:

mkdir GradleProject # 创建我们的工作目录
mkdir ScriptPlugin # 创建脚本插件的项目目录

touch build.gradle hello.gradle # 创建两个gradle文件
复制代码

hello.gradle的内容:

task("hello") {
    doLast {
        println "Hello, Script Plugin!"
    }
}
复制代码

没什么说的,就是创建一个简单的Task。

build.gradle的内容:

apply from: "hello.gradle"
复制代码

**gradle中通过apply函数进行文件引用、插件引用等。**这里使用from作为key进行hello.gradle文件的引用。

最后执行:

gradle hello
复制代码

可以看到成功地执行了名为hello的Task。

buildSrc目录

在讲对象插件之前,先说一下这个目录。**每个项目中这个目录中的类会在gradle进行构建的是进行代码的编译。**使用对象插件一种简单的方式就是在此目录下写插件相关的逻辑。

只不过这样做有一个很大的缺点就是该项目中进行插件的引用。

对象插件

对象插件可以用任何的JVM语言进行编写,比如说:Groovy、 Java 、Kotlin等都行。本篇博客中将使用Groovy进行编写。

buildSrc中实现

文件结构总览:

聊聊Gradle插件

回到GradleProject目录下,执行下面的命令:

mkdir Plugin
cd Plugin
mkdir -p buildSrc/src/main/groovy/com/anriku/plugin/
mkdir -p buildSrc/src/main/resources/META-INF/gradle-plugins/

// 进行文件的创建
touch build.gradle
buildSrc/src/main/groovy/com/anriku/plugin/HelloPlugin.groovy buildSrc/src/main/groovy/com/anriku/plugin/HelloTask.groovy
buildSrc/src/main/groovy/com/anriku/plugin/HelloExtension.groovy
buildSrc/src/main/resources/META-INF/gradle-plugins/plugin.properties
复制代码

HelloTask.groovy:

package com.anriku.plugin

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction

class HelloTask extends DefaultTask{

  	// @Input指出Task接收的输入,当对应输入为null将会抛异常。解决方法是加上@Optional注解。
    @Input String firstName
    @Input String lastName

  	// @TaskAction指明Task的Action
    @TaskAction
    void greet() {
      	// 这里只能调用getFirstName()和getLastName()(不能使用firstName、lastName)是因为在后面的插件
      	// 中使用的是约定映射conventionMapping
        println "Hello," + getFirstName() + " " +  getLastName()
    }
}
复制代码

这是一个自定义的Task类。接收firstName、lastName进行一个问候语打印。

HelloTaskExtension.groovy:

package com.anriku.plugin

class HelloTaskExtension {

    String extFirstName
    String extLastName

}
复制代码

此类为 扩展对象 ,主要作用是为了给插件设置一些在构建脚本中可以设定的 属性

HelloPlugin.groovy:

package com.anriku.plugin

import org.gradle.api.Plugin
import org.gradle.api.Project


class HelloPlugin implements Plugin<Project> {

		// 扩展对象在构建脚本中的名字
    static final String EXTENTION_NAME = "helloExtension"

    @Override
    void apply(Project project) {
      	// 给project创建扩展对象
        project.extensions.create(EXTENTION_NAME, HelloTaskExtension)
        project.task("hello", type: HelloTask) { task ->
          	// 读取扩展对象的中设置的值并赋值给Task对应的约定映射
            def extension = project.extensions.findByName(EXTENTION_NAME)
            conventionMapping.firstName = { extension.extFirstName }
            conventionMapping.lastName = { extension.extLastName }
        }
    }
}
复制代码

自定义的Plugin继承自 org.gradle.api.Plugin ,覆写的apply方法用于写实现逻辑。

这里主要完成了两个任务:

helloExtension
hello

conventionMapping叫做约定映射,每个继承于DefalutTask的类都有,它的主要作用就是确保扩展属性可以在运行时赋值。

PS:约定映射设置的属性在Task中必须要显示的使用getter进行获取。可以回头看下自定义的Task的实现。

plugin.properties

implementation-class=com.anriku.plugin.HelloPlugin
复制代码

此文件实现很简单, 它作用就是简化apply plugin的使用。

假设文件名为 xxx.properties

那么可以使用 apply plugin: 'xxx' -> apply plugin: 类的全限定名

PS:其中前面的方式是 字符串 ,后面的方式是 类名

build.gradle

// 之所以能这么使用就是上面的文件进行了设定。
apply plugin: "plugin"

// 下面是扩展对象完成的功能
helloExtension {
    extFirstName = "anriku"
    extLastName = "wen"
}
复制代码

现在在 /.../Plugin 目录下执行 gradle hello ,没有出错应该是能成功引用插件。

独立的对象插件

对于上面在buildSrc中实现对象插件的方式有一个问题就是这个对象插件只能够被当前项目所使用。如果想要给多个项目使用这时候就需要独立的对象插件。

文件总览:

聊聊Gradle插件

现在仍然会到GradleProject目录下执行下面的命令

# 创建项目
mkdir StandalonePlugin
cd StandalonePlugin

# 创建目录
mkdir Application
mkdir -p Plugin/src/main/groovy/com/anriku/standaloneplugin
mkdir -p Plugin/src/main/resources/META-INF/gradle-plugins

# 创建文件
touch Plugin/build.gradle Application/build.gradle
Plugin/src/main/groovy/com/anriku/standaloneplugin/HelloPlugin.groovy
Plugin/src/main/groovy/com/anriku/standaloneplugin/HelloTask.groovy
Plugin/src/main/groovy/com/anriku/standaloneplugin/HelloTaskExtension.groovy
Plugin/src/main/reources/META-INF/gradle-plugins/standaloneplugin.properties
复制代码

HelloPlugin.groovy、HelloTask.groovy、HelloTaskExtension.groovy和上面一节中的基本一样(只是把包名改一下);standaloneplugin.properties的内容和上面一小节的类似(不过同样要把包名改一下)。

Plugin中的build.gradle

plugins {
    id 'groovy'
  	// maven插件用于将上传插件,这里我们进行的是本地插件的部署
    id 'maven'
}

// 插件的classpath将会由下面的参数决定。下面组成的classpath将是com.anriku:standaloneplugin:1.0
group 'com.anriku'
version '1.0'
archivesBaseName = 'standaloneplugin'

dependencies {
   	// 由于在插件的编写中使用到了Gradle相关的类。比如说:org.gradle.api.Plugin。因此这里需要添加对
    // Gradle API的支持。上面在buildSrc目录可以直接使用Gradle API。
    implementation gradleApi()
}

// maven预定的发布插件的Task
uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: "file://$projectDir/../repo")
        }
    }
}
复制代码

在Plugin目录下的的build.gradle主要是一些 发布本地插件 相关的构建逻辑。

在Plugin目录下执行 gradle uploadArchives 命令没有出错的话,应该会产生一个与Plugin目录同级的repo目录。本地插件就以jar包的形式放在此目录下。

Application中的build.gradle

// 在buildScript中添加对刚才发布的插件的依赖
buildscript {
    repositories {
      	// 插件的位置
        maven { url "file://$projectDir/../repo" }
    }

    dependencies {
      	// 插件的classpath,就是刚才对group、version、archivesBaseName的设置。
        classpath 'com.anriku:standaloneplugin:1.0'
    }
}

// 使用插件。当然也可以使用apply com.anriku.standaloneplugin.HelloPlugin
apply plugin: 'standaloneplugin'

// hello Task的扩展对象
helloExtension {
    extFirstName = "anriku"
    extLastName = "wen"
}
复制代码

在Application目录下执行 gradle hello 。成功出现 Hello,anriku wen 就说明成功了。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Rationality for Mortals

Rationality for Mortals

Gerd Gigerenzer / Oxford University Press, USA / 2008-05-02 / USD 65.00

Gerd Gigerenzer's influential work examines the rationality of individuals not from the perspective of logic or probability, but from the point of view of adaptation to the real world of human behavio......一起来看看 《Rationality for Mortals》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码