编写Plugin插件
定义TestCodePlugin然后实现Plugin<T> 实现apply方法,最后apply plugin:TestCodePlugin.class这样就定义好了plugin插件了,如下:
image.png
如何执行呢?可以在终端窗口输入./gradlew,由于apply方法中没有任何执行的代码?这里是没法看到我们执行了apply方法 ,我们可以在apply方法中输出一个println("hello plugin!!!"),然后执行./gradlew ,通过查找就能在终端中找到hello plugin 太神奇了,有没有!!!
代码如下:
image.png
这样简单的plugin插件就写好了,这很显然是非常简单的,那么我们逐步来揭秘gradle插件的奥秘
如何来实现apply方法呢?如何使用呢?这里也可以使用简单的方式来实现
首先可以在apply plugin:TestCodePlugin 下方定义testCodePlugin{}闭包
然后定义TestExtension类,设置一个成员变量 字符串的name = "i`m test extension",
最后在实现apply方法,这里我们会发现apply方法中有一个Project target参数,我们可以利用这个参数来实现我们想要的效果,比如说我们如何在testCodePlugin实现取出TestExtension中的name并在apply方法中打印出name的内容,就要用到apply参数target
定义def extension = target.extensions.create('testCodePlugin', TestExtension),其实我们会发现这里就是相当于初始化TestExtension ,并于testCodePlugin关联起来,因为我们这里是使用的plugin插件,其实也很好理解
打印println("$extension.name"),再执行./gradlew 打印结果
public class TestExtension {
String name = "i`m modify test extension"
}
its amazing. 打怪升级!!!如果你是刚接触gradle 通过上面的示例也许你就能够初步了解gradle了,是不是没想到,gradle插件可以这样玩。
针对name来做一些事情,变量是可以修改的,那么我们如何实现通过修改name的内容来完成修改name的内容呢?不卖关子了,可以直接在testCodePlugin中通过name "i`m modify test extension",再次执行./gradlew ,查看结果
image.png
比较尴尬,如果仔细的读者会发现,你这里的内容不还是之前的吗?我想告诉你的是你是一个很好的读者!!!被你发现了,尴尬 按你这样写应该没问题吧,这个就要讲到gradle相关的内容,你知道gradle中的task吗,也许你没用过,如果你看我这篇文章也应该听过吧 ,不知道没关系!!!
比如我们定义一个task test
task test{
doFirst{
println("I execute doFirst")
}
doLast{
println("I execute doLast")
}
}
通过./gradlew 你会发现什么?这里我就不做测试了,你可以尝试下,我就直接说结果,你会发现这段代码的内容是没有被打印出来的
其实我们这里也遇到了相同的问题,也就是这里的testCodePlugin没有被执行
ok 知道原因就好办了,这里可以使用target中的afterEvaluate 也就是延迟执行闭包的
target.afterEvaluate {
println("$extension.name")
}
再次执行./gradlew 打印结果
image.png
意不意外,神不神奇 是不是对gradle又燃起了想要学习的冲动!!!
上面只是小试牛刀,我们再来个升级版的
上面讲了gradle的插件,那么为什么我们要使用它呢?他有什么用。他能解决什么问题!!!
当然如果我们学习知识带有目的性这本身就不是很好吧,学习知识就是因为喜 有一个好处,就是一次配置到处用,他可以解决的问题也就是因为这。也就是你只需写一份配置通过apply plugin:xxx,你就可以使用了,简单 高效 避免写重复的code这不就是我们想要的吗?
好了讲了如何有用,现在进入正题!!!如何写一个plugin插件,我们可以把plugin插件单独创建一个module,步骤如下:
image.png
注意选择module的java library
image.png
点击next名称你可以自己定义,我这里叫buildSrc ,名称还是要讲究的,可以使用方法的名称命名就可以了 首字母小写其他的单字的首字母大写,如上
创建完后 在gradle中打印println("This is a buildSrc Library")执行./gradlew命令
在终端窗口你会发现打印的内容执行了两次
image.png
这又是为什么呢?这个就要了解项目是如何运行的,首先它会先执行plugin库,然后通过settings.gradle文件中配置的顺序又重新执行了一遍。这里我们只需要把settings.gradle中配置plugin库去掉即可。
现在我们就可以编写自己的plugin了。我们可以把默认的MyClass改下名称-TestPlugin实现Plugin接口,你会发现怎么没有我们想要的Plugin呢
什么鬼!!!没有只能说明你没有配置呗,作为一个程序员还是要有点耐心的,如果配置呢?那我们就要知道这个gradle是怎么配置的吧,我们学的不就是gradle相关的知识吗,这里我们应该就知道了 ,这个配置是在root gradle中的
image.png
打开root gradle找到gradle相关的配置,然后在复制到plugin中的gradle中即可,这里要注意的是
repositories {
google()
jcenter()
}
这个也要copy一份到你的Plugin Module中,为什么呢?我们首先要了解这是什么 对不对 对于刚接触到android对这个不是很了解的小伙伴讲解一下,这个就是你配置的gradle的来源,如果不配置这个。我们就找不到gradle的来源,也就会提示下载失败什么的,这个相信很多有经验的程序员也同样的遇到过类似的问题。
image.png
配置如下:
repositories {
google()
jcenter()
}
dependencies {
implementation 'com.android.tools.build:gradle:3.5.2'
}
点击右上方的同步,编译完成后我们就可以在module中编写我们的代码,这里要注意下,由于gradle中使用的语言是groovy,我们在module中编写也适用groovy语言编写。
本身为了学习,为了简单,那么我们可以使用TestPlugin和TestExtension也就是我们上面讲解的内容。为了不啰嗦,我这里直接就把包结构和资源粘贴下
image.png
这里需要注意的就是把我们的java换成groovy,以及TestPlugin文件后缀.properties
好了这样简单的plugin插件大功告成
在app中gradle中配置下,如下:
apply plugin:'TestPlugin'
testPlugin{
name 'i`m test extension!!!'
}
然后执行./gradlew 命令 打印日志如下:
transform的使用
自定义TestTransform 继承Transform重写里面的方法,getInputTypesdes 这个是你插件需要的类型通过TransformManager.xxx就可以选择你需要的类型,这里有class jar. resources 等等 getScope你需要多大的范围处理这个插件 TransformManager.SC image.pngOPE_xxx你可以自行选择,先截屏让大家更直观的了解TransformManager
还有一个getName需要返回一个String类型 这有是什么呢?
我们通过设置getName,能够让大家直观的了解这是什么,截个屏大家都明白这是什么了
image.png
然后在TestPlugin中编写如下代码:
def testTransform = new TestTransform()
def testBaseExtension = project.extensions.getByType(BaseExtension)
testBaseExtension.registerTransform(testTransform)
在TestTransform 中重写transform方法,这个方法有什么用呢?就是把之前配置过的文件放在目标目录,这里我们只需把这些文件输出到目标目录下就ok了
def inputs = transformInvocation.inputs
def outputProvider = transformInvocation.outputProvider
inputs.each {
it.jarInputs.each {
File dest = outputProvider.getContentLocation(it.name, it.contentTypes, it.scopes, Format.JAR)
println "Jar:$it.file"
FileUtils.copyFile(it.file,dest)
}
it.directoryInputs.each {
File dest = outputProvider.getContentLocation(it.name, it.contentTypes, it.scopes, Format.DIRECTORY)
println "Dir:$it.file"
FileUtils.copyDirectory(it.file,dest)
}
}
好了gradle配置相关的基础知识这篇文章就讲完了,创作不易,如果对你有帮助,记得动动你的小手指,点个赞也很不错
代码传送门 如果对你有用记得star 🙏🙏🙏
网友评论