Now In Android 精讲 8 - Gradle build-logic 现代构建逻辑组织方式

在学习 Now in Android 这个项目的时候,相信很多人都会注意到他使用了 build-logic 来构建整个仓库的配置,相信很多人都想知道他跟以前的方式究竟有何异同,本文就抱着常见的问题来逐步学习,到底为何要使用 build-logic?

build-logic 与 buildSrc 到底有何区别?

说到 build-logic 自然离不开 buildSrc,很多人看来他俩的功能差不多,那么为什么要使用 build logic呢?

构建隔离

  • buildSrc:作为项目的一部分被构建,当 buildSrc 变更时,整个项目需要重新构建
  • build-logic :通过 Gradle 的 Composite Build 功能(includeBuild)作为独立构建被包含,享有更好的构建隔离性

缓存机制

  • buildSrc:与主项目共享缓存,导致 buildSrc 的变更会使整个项目缓存失效
  • build-logic:拥有独立的缓存,修改不会影响主项目的缓存,提高构建效率

版本控制与依赖管理

  • buildSrc:直接继承主项目的依赖和版本
  • build-logic:可以有自己独立的版本控制和依赖管理

Now in Android 中的 build-logic 结构

Now in Android 项目使用 build-logic 集中管理所有构建逻辑,其主要结构如下:

css 复制代码
build-logic/
├── convention/
│   ├── src/main/kotlin/
│   │   ├── AndroidApplicationConventionPlugin.kt
│   │   ├── AndroidLibraryConventionPlugin.kt
│   │   ├── AndroidFeatureConventionPlugin.kt
│   │   └── ...其他插件
│   └── build.gradle.kts
├── settings.gradle.kts
└── gradle.properties

在这里面,希望大家对 convention 这个单词有一些了解,它的含义是:习惯的,约定俗成的。所以在这里面是项目里面大家对于代码风格,仓库等模块的约定配置。是一个公共配置模块,是用来存放共有配置的地方。大家都知道,如果修改项目的 build.gradle 会导致缓存内容的失效,但是如果我公共的配置放置在 convention plugin 里面,我的修改就不会引起项目的re-sync,这样会节省开发等待时间。

主要约定插件分析

Now in Android 项目中的 build-logic 包含多个约定插件(Convention Plugins),每个负责特定类型模块的构建配置。以下是核心插件的功能分析:

1. AndroidApplicationConventionPlugin

该插件负责配置应用模块的基本设置:

kt 复制代码
class AndroidApplicationConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            apply(plugin = "com.android.application")
            apply(plugin = "org.jetbrains.kotlin.android")
            apply(plugin = "nowinandroid.android.lint")
            
            extensions.configure<ApplicationExtension> {
                configureKotlinAndroid(this)
                defaultConfig.targetSdk = 35
                // ...其他配置
            }
            // ...其他扩展配置
        }
    }
}


internal fun Project.configureKotlinAndroid(
    commonExtension: CommonExtension<*, *, *, *, *, *>,
) {
    commonExtension.apply {
        compileSdk = 35

        defaultConfig {
            minSdk = 21
        }

        compileOptions {
            // Up to Java 11 APIs are available through desugaring
            // https://developer.android.com/studio/write/java11-minimal-support-table
            sourceCompatibility = JavaVersion.VERSION_11
            targetCompatibility = JavaVersion.VERSION_11
            isCoreLibraryDesugaringEnabled = true
        }
    }

    configureKotlin<KotlinAndroidProjectExtension>()

    dependencies {
        "coreLibraryDesugaring"(libs.findLibrary("android.desugarJdkLibs").get())
    }
}

这个插件应用了基本的 Android 应用插件,并配置了 Kotlin Android、Lint 检查等通用设置。

2. AndroidLibraryConventionPlugin

该插件配置 Android 库模块:

kotlin 复制代码
class AndroidLibraryConventionPlugin : Plugin<Project> {
    override fun apply(target: Project) {
        with(target) {
            apply(plugin = "com.android.library")
            apply(plugin = "org.jetbrains.kotlin.android")
            apply(plugin = "nowinandroid.android.lint")

            extensions.configure<LibraryExtension> {
                configureKotlinAndroid(this)
                defaultConfig.targetSdk = 35
                // 自动生成资源前缀,确保模块资源命名一致性
                resourcePrefix = path.split("""\W""".toRegex())
                    .drop(1).distinct().joinToString(separator = "_").lowercase() + "_"
                // ...其他配置
            }
            // ...其他扩展配置
        }
    }
}

该插件不仅配置了 Android 库的基本设置,还自动生成了基于模块路径的资源前缀,确保了项目资源命名的一致性。

3. 功能模块插件

针对特定功能需求,Now in Android 项目还提供了多个专门的插件:

  • AndroidFeatureConventionPlugin:为功能模块添加常用依赖(ViewModel、Hilt等)
  • AndroidRoomConventionPlugin:配置 Room 数据库
  • HiltConventionPlugin:配置 Hilt 依赖注入
  • AndroidLibraryComposeConventionPlugin:为库模块添加 Compose 支持

插件注册与使用

插件注册

所有插件在 build-logic/convention/build.gradle.kts 中通过 gradlePlugin DSL 注册:

kotlin 复制代码
gradlePlugin {
    plugins {
        register("androidLibrary") {
            id = libs.plugins.nowinandroid.android.library.asProvider().get().pluginId
            implementationClass = "AndroidLibraryConventionPlugin"
        }
        // ...其他插件注册
    }
}

插件使用

而在需要 library 支持的模块中,如 core/designsystem

kotlin 复制代码
// core/designsystem/build.gradle.kts
plugins {
    alias(libs.plugins.nowinandroid.android.library)
    alias(libs.plugins.nowinandroid.android.library.compose)
    alias(libs.plugins.nowinandroid.android.library.jacoco)
}

android {
    namespace = "com.google.samples.apps.nowinandroid.core.designsystem"
}

通过这种方式,复杂的构建逻辑被封装在插件中,模块的构建脚本保持简洁明了。

约定插件的开发

  1. 首先是创建常见的需要配置的模块,例如上面的代码 AndroidApplicationConventionPlugin
  2. 配置依赖的插件,例如 apply(plugin = "com.android.application")
  3. configure对需要统一配置的参数进行配置
  4. 如果 config 的内容较多可以创建一个拓展函数进行配置,例如上面的的 configureKotlinAndroid

整体而言,convention plugin 给大家对于常见的配置环节有了一个统一地方,但是在开发的时候要按照约定进行命名,这样大家才能更快的熟悉其中的代码。

build-logic 的优势

采用 build-logic方式组织构建逻辑有以下显著优势:

  1. 提高构建性能:独立的缓存机制减少了不必要的重新构建
  2. 增强代码复用:避免在每个模块重复相同的构建配置
  3. 保证构建一致性:所有模块遵循相同的构建标准和最佳实践
  4. 简化模块配置:大幅减少各模块 build.gradle 文件的复杂度
  5. 便于维护与更新:集中管理构建逻辑,全局性变更只需修改一处

结尾

通过 Now in Android 项目的实践可以看出,build-logic 作为现代 Gradle 构建逻辑组织方式,相比传统的 buildSrc 方法提供了更好的构建隔离性、缓存机制和维护性。它特别适合大型多模块项目,能有效提高构建效率、减少配置重复,并确保构建逻辑的一致性和可维护性。

随着 Android 项目复杂度的不断提高,采用 build-logic 这类先进的构建组织方式将成为大型项目的优选方案。如果你正在开发或维护一个多模块的 Android 项目,不妨考虑迁移到这种模式,享受它带来的诸多好处。

相关推荐
婵鸣空啼3 小时前
GD图像处理与SESSiON
android
sunly_4 小时前
Flutter:导航固定背景图,滚动时导航颜色渐变
android·javascript·flutter
用户2018792831674 小时前
简单了解android.permission.MEDIA_CONTENT_CONTROL权限
android
_一条咸鱼_4 小时前
Android Runtime类卸载条件与资源回收策略(29)
android·面试·android jetpack
顾林海4 小时前
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
android·面试·性能优化
玲小珑5 小时前
Auto.js 入门指南(八)高级控件与 UI 自动化
android·前端
harry235day5 小时前
Compose 带动画的待办清单列表页
android·android jetpack
vocal5 小时前
我的安卓第一课:四大组件之一Activity及其组件RecyclerView
android
咕噜企业签名分发-淼淼5 小时前
如何实现安卓端与苹果端互通的多种方案
android