Now In Android学习大项目是怎么构建程序的

2,914 阅读3分钟

NowInAndroid学习系列

Now in Android !AndroidApp开发的最佳实践,让我看看是怎么个事?

Now in Android学习Compose是怎么切换主题

1、Now In Android 的依赖版本管理 versioncatLog

Android Gradle 依赖版本管理的演变

早期的手动管理

在早期的Android开发中,依赖版本完全由开发者手动管理,每个依赖版本号都需要在build.gradle文件中显示指定。这种方式容易导致版本不一致和依赖冲突问题。

引入 ext 块

为了解决版本不一致的问题,Gradle引入了ext块来集中管理依赖版本,在项目的根build.gradle文件中定义版本变量,然后在子模块中引用这些变量

根目录build.gradle

ext {
         supportLibraryVersion = '28.0.0'
     }

子模块

dependencies {
         implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
     }

使用dependencies块

gradle4.0之后,引入dependencies块来更方便的管理依赖。 可以在dependencies块里直接定义变量。

dependencies {
         def supportLibraryVersion = '28.0.0'
         implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
     }

引入 versionCataLogs

Gradle7.0之后,引入了versionCatalogs功能,进一步简化了依赖管理。versionCatalogs 允许在一个单独的文件中集中管理所有依赖和版本。

而在Now In Android中,使用的就是最后一种方式,也是谷狗官方推荐的方式。非常的银杏。。。

toml 总结构

image.png

libraies和plugins 引用version里面的变量,

image.png

模块引用

image.png

2、Now In Android 插件管理

Now In Android 对插件的管理,那也是非常的银杏。银杏的我都看不懂,所以,大家一起来看看。 对于插件,需要引入的依赖比较多的,他是怎么提升代码简洁和代码复用的呢。通过自定义插件,将别的插件再封装一下。
Hilt插件为例,注册一个Now in Android的Hilt插件

image.png

gradlePlugin 块: 这个块用于定义 Gradle 插件。它告诉 Gradle 这个项目将包含自定义插件。 plugins 块: 在 gradlePlugin 块内部,plugins 块用于注册具体的插件。 register 方法: register 方法用于注册一个新的插件。它接受一个字符串参数作为插件的名称,这里是 "hilt"。 id 属性: id 属性定义了插件的唯一标识符,这里是 "nowinandroid.hilt"。这个标识符可以在其他项目中引用该插件。 implementationClass 属性: implementationClass 属性指定了实现该插件的类的全限定名,这里是 "HiltConventionPlugin"。这个类必须实现 org.gradle.api.Plugin 接口,并且包含插件的具体逻辑。

我们去看看具体的接口实现

image.png 这一个类,包含了Hilt用到的所有依赖,ksp,hiltcore ,hilt.andor,还有android.Plugin ,还有hint.compiler 自定义完这个插件之后,我们在其他模块,用到hint的时候,只需要引入我们自定义的插件即可,这样既方便,又简洁,还便于管理,是不是很Nice。很舒服

其他模块的应用

image.png 这里,用toml管理了插件版本,用自定义插件的方式复用了代码。还是很nice的。所有需要引入很多的依赖组,都可以这样做。

3、Now in Android具体的Gradle实战

3.1 root.gradle

定义了gradle,依赖的仓库,还有用到的所有的插件

image.png

3.2 build-logic-Convention模块的gradle

所有的自定义插件,都放在这里面,然后被,build-logic的settings.gradle引用

import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    `kotlin-dsl`
}

group = "com.google.samples.apps.nowinandroid.buildlogic"

// Configure the build-logic plugins to target JDK 17
// This matches the JDK used to build the project, and is not related to what is running on device.
java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

kotlin {
    compilerOptions {
        jvmTarget = JvmTarget.JVM_17
    }
}

dependencies {
    compileOnly(libs.android.gradlePlugin)
    compileOnly(libs.android.tools.common)
    compileOnly(libs.compose.gradlePlugin)
    compileOnly(libs.firebase.crashlytics.gradlePlugin)
    compileOnly(libs.firebase.performance.gradlePlugin)
    compileOnly(libs.kotlin.gradlePlugin)
    compileOnly(libs.ksp.gradlePlugin)
    compileOnly(libs.room.gradlePlugin)
    implementation(libs.truth)
}

tasks {
    validatePlugins {
        enableStricterValidation = true
        failOnWarning = true
    }
}

gradlePlugin {
    plugins {

        register("hilt") {
            id = "nowinandroid.hilt"
            implementationClass = "HiltConventionPlugin"
        }
         register("androidApplicationCompose") {
            id = "nowinandroid.android.application.compose"
            implementationClass = "AndroidApplicationComposeConventionPlugin"
        }
        register("androidApplication") {
            id = "nowinandroid.android.application"
            implementationClass = "AndroidApplicationConventionPlugin"
        }
        register("androidApplicationJacoco") {
            id = "nowinandroid.android.application.jacoco"
            implementationClass = "AndroidApplicationJacocoConventionPlugin"
        }
        register("androidLibraryCompose") {
            id = "nowinandroid.android.library.compose"
            implementationClass = "AndroidLibraryComposeConventionPlugin"
        }
        register("androidLibrary") {
            id = "nowinandroid.android.library"
            implementationClass = "AndroidLibraryConventionPlugin"
        }
        register("androidFeature") {
            id = "nowinandroid.android.feature"
            implementationClass = "AndroidFeatureConventionPlugin"
        }
        register("androidLibraryJacoco") {
            id = "nowinandroid.android.library.jacoco"
            implementationClass = "AndroidLibraryJacocoConventionPlugin"
        }
        register("androidTest") {
            id = "nowinandroid.android.test"
            implementationClass = "AndroidTestConventionPlugin"
        }
        register("androidRoom") {
            id = "nowinandroid.android.room"
            implementationClass = "AndroidRoomConventionPlugin"
        }
        register("androidFirebase") {
            id = "nowinandroid.android.application.firebase"
            implementationClass = "AndroidApplicationFirebaseConventionPlugin"
        }
        register("androidFlavors") {
            id = "nowinandroid.android.application.flavors"
            implementationClass = "AndroidApplicationFlavorsConventionPlugin"
        }
        register("androidLint") {
            id = "nowinandroid.android.lint"
            implementationClass = "AndroidLintConventionPlugin"
        }
        register("jvmLibrary") {
            id = "nowinandroid.jvm.library"
            implementationClass = "JvmLibraryConventionPlugin"
        }
    }
}

build-logic的settings.gradle image.png

3.3 项目的settings.gradle引入build-logic的settings.gradle

image.png 剩下的就是模块化,之间的各种依赖了。

4、总结

这篇就是这些。我认为值得学习的地方,只把逻辑给大家捋一遍。想要知道具体的细节,可以去github,down一份源码,细细的食用。