一、插件到底是个啥?
说实话,我刚接触 Gradle 那会儿,对「插件」这个概念挺模糊的。总觉得它是个很玄乎的东西,好像离我很远。
后来做项目做多了,慢慢就明白了——插件其实就是一段可复用的构建逻辑。你想想看,我们每天都在用插件:
- apply plugin: 'com.android.application' —— 这是 Android 官方插件
- apply plugin: 'kotlin-android' —— 这是 Kotlin 插件
- apply plugin: 'com.google.gms.google-services' —— 这是 Google 服务插件
说白了,插件就是把一堆 Task、配置、扩展属性打包起来,让你能一键复用。没有插件的话,你每个项目都得手写那些编译、打包、签名、混淆的逻辑……想想就头大。
二、插件的三种类型
Gradle 插件分三种,我按使用场景给你捋一捋。
1. 脚本插件
这是最原始、最直接的方式。说白了就是一个 .gradle 文件,里面写一堆逻辑,然后别的脚本用 apply from 把它引进来。
// version.gradle
ext {
compileSdkVersion = 34
minSdkVersion = 21
targetSdkVersion = 34
}
// app/build.gradle
apply from: '../version.gradle'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
// ...
}
我在早期项目里经常这么干。好处是简单,坏处是……嗯,你没法控制别人怎么用你的脚本,也没法传参数。说白了就是「裸奔」。
2. 二进制插件
这就是我们平时用的那种插件。它被打包成 jar 或者 aar,通过 apply plugin: '插件ID' 来使用。Android 插件、Kotlin 插件都属于这一类。
二进制插件的好处是:
- 可以传参数(通过 extension)
- 可以控制执行顺序
- 可以依赖其他插件
- 可以发布到仓库供别人使用
3. 预编译脚本插件
这是 Gradle 7.0 之后推出的新玩法。它本质上还是脚本,但被编译成了 .class 文件,所以性能更好,而且可以像二进制插件一样用 apply plugin 来引用。
// buildSrc/src/main/kotlin/my-library.gradle.kts
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
}
android {
compileSdk = 34
defaultConfig {
minSdk = 21
}
}
// app/build.gradle.kts
plugins {
id("my-library")
}
我个人比较推荐这种方式。它既有脚本的灵活性,又有二进制插件的性能。我在团队里推广过,大家反馈都不错。
三、三种插件的对比
| 类型 | 定义方式 | 使用方式 | 性能 | 适用场景 |
|---|---|---|---|---|
| 脚本插件 | .gradle 文件 | apply from | 一般 | 简单配置共享 |
| 二进制插件 | Java/Kotlin 类 | apply plugin | 好 | 复杂构建逻辑 |
| 预编译脚本插件 | .gradle.kts 文件 | apply plugin | 较好 | 模块化配置 |
四、知识体系总览
在动手写插件之前,我们先看看整个知识结构长什么样:
五、创建第一个自定义插件
好,理论说完了,咱们动手写一个。我带你写一个最简单的插件——它只做一件事:在构建开始前打印一条日志。
步骤 1:创建 buildSrc 模块
在项目根目录下创建 buildSrc 文件夹,里面放一个 build.gradle.kts:
// buildSrc/build.gradle.kts
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
然后创建源码目录:buildSrc/src/main/kotlin/
步骤 2:写插件类
// buildSrc/src/main/kotlin/com/example/HelloPlugin.kt
package com.example
import org.gradle.api.Plugin
import org.gradle.api.Project
class HelloPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.register("hello") {
doLast {
println("👋 Hello from my first plugin!")
}
}
}
}
这里要注意,Plugin 接口的泛型参数是 Project。这意味着你的插件作用于整个 Project 层面。如果你想作用于某个 Task,那又是另一种写法了。
步骤 3:注册插件 ID
在 buildSrc/src/main/resources/META-INF/gradle-plugins/ 目录下,创建一个 properties 文件:
# buildSrc/src/main/resources/META-INF/gradle-plugins/com.example.hello.properties
implementation-class=com.example.HelloPlugin
文件名就是你的插件 ID。我习惯用包名作为前缀,这样不容易冲突。
步骤 4:使用插件
// app/build.gradle.kts
plugins {
id("com.example.hello")
}
然后执行 ./gradlew hello,你就会看到控制台打印出那句问候语。
六、发布到本地仓库
插件写好了,总不能只在 buildSrc 里用吧?我想把它发布到本地仓库,让其他项目也能引用。
步骤 1:配置发布脚本
在插件的 build.gradle.kts 里加上 maven-publish 插件:
plugins {
`kotlin-dsl`
`maven-publish`
}
group = "com.example"
version = "1.0.0"
publishing {
publications {
create<MavenPublication>("plugin") {
from(components["kotlin"])
}
}
repositories {
maven {
name = "localRepo"
url = uri("${rootProject.projectDir}/repo")
}
}
}
步骤 2:执行发布
运行 ./gradlew publishPluginPublicationToLocalRepoRepository,插件就会被发布到项目根目录下的 repo 文件夹里。
步骤 3:在其他项目中使用
// settings.gradle.kts
pluginManagement {
repositories {
maven {
url = uri("${rootProject.projectDir}/repo")
}
gradlePluginPortal()
google()
mavenCentral()
}
}
// app/build.gradle.kts
plugins {
id("com.example.hello") version "1.0.0"
}
七、总结一下
这一章我们聊了:
- 插件是什么——说白了就是构建逻辑的封装
- 三种插件类型——脚本、二进制、预编译脚本
- 怎么创建第一个插件——从 buildSrc 开始
- 怎么发布到本地仓库——用 maven-publish
我个人觉得,插件开发是 Gradle 进阶路上必须跨过的一道坎。它不难,但需要你理解 Gradle 的运作方式。下一章我们会深入插件的内部结构,看看 extension 和 task 是怎么配合的。
嗯,今天就到这儿。动手试试吧,有问题随时交流。