Skip to content

约定插件深度实践

在大型 Android 项目中,简单的“逻辑提取”往往不足以支撑复杂的构建需求。本章将深入探讨如何构建工业级的约定插件(Convention Plugins)体系,实现全项目构建逻辑的高度内聚与复用。

插件体系架构设计

推荐采用类似 Now in Android 的分层模式:

  1. 基础插件: 处理 Kotlin 编译、Java 版本、代码质量。
  2. Android 核心插件: 处理 AGP 通用配置(compileSdk, buildFeatures)。
  3. 应用/库专项插件: 区分 :app:library 的特定配置(如签名、混淆)。
  4. 功能插件: 可选功能(如 Hilt, Compose, Room)。

在插件中访问 Version Catalog

在独立的项目(如 build-logic)中编写插件时,不能直接使用 libs.xxx。你需要通过扩展函数来优雅地访问它。

kotlin
// build-logic/convention/src/main/kotlin/com/myapp/ProjectExtensions.kt
internal val Project.libs
    get(): VersionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")

// 使用示例
internal fun Project.configureKotlinAndroid(commonExtension: CommonExtension<*, *, *, *, *, *>) {
    commonExtension.apply {
        compileSdk = libs.findVersion("compileSdk").get().requiredVersion.toInt()
        // ...
    }
}

编写可配置的扩展 (Extensions)

好的约定插件应该允许调用者进行微调,而不是死板的“一刀切”。

kotlin
// 定义扩展
interface MyLibraryExtension {
    val enableCompose: Property<Boolean>
}

// 在插件中注册
val extension = extensions.create<MyLibraryExtension>("myLibrary")

// 根据配置执行逻辑
if (extension.enableCompose.getOrElse(false)) {
    applyComposeConfiguration()
}

统一处理依赖组

你可以在约定插件中统一引入所有模块都需要的依赖(如:单元测试工具、性能监控),避免漏写。

kotlin
dependencies {
    add("testImplementation", libs.findLibrary("junit").get())
    add("androidTestImplementation", libs.findLibrary("androidx.test.ext.junit").get())
}

工业级实战:功能开关模式

通过在 gradle.properties 或自定义扩展中定义开关,让插件具备极强的灵活性。

kotlin
// 插件逻辑
onVariants { variant ->
    if (project.hasProperty("my.instrumentation.enabled")) {
        // 动态开启字节码插桩
    }
}

总结

约定插件不是简单的“代码搬运”,而是构建系统的“组件化”。通过 “复合构建 + 约定插件 + 强类型访问 Version Catalog” 的组合,你可以将 100 个模块的维护成本降低到极致。