阅读 509

Android 依赖管理及通用项目配置插件

本文主要内容:

  1. 依赖管理:gradle 插件 7.0 以上版本使用 version catalog 进行依赖管理

  2. 通用编译扩展属性管理:在插件工程配置各子工程通用的扩展属性、插件、依赖

  3. 插件工程:插件工程和主工程混合编译,以及 gradle 插件 7.0 以上版本如何发布到 jitpack。


现在的项目基本都是多模块结构,每次新增模块都复制一遍 minSdktargetSdk 之类的通用扩展属性会比较麻烦,应该用通用的插件来管理。

1 插件使用

插件使用案例:plugin/sample

插件源码: feature/plugin

1.1 添加依赖


方式一:

// 项目根目录 build.gradle.kts buildscript {     repositories {         maven { setUrl("https://jitpack.io") }     }     dependencies {         classpath("com.github.Jadyli.composing:config-plugin:0.1.2")     } } 复制代码


方式二(推荐):

// 项目根目录 settings.gradle.kts pluginManagement {     repositories {         maven { setUrl("https://jitpack.io") }     }     resolutionStrategy {         eachPlugin {             when (requested.id.id) {                 "com.jady.lib.config-plugin" -> {                     useModule("com.github.Jadyli.composing:config-plugin:0.1.2")                 }             }         }     } } 复制代码

1.2 配置 sdk 版本:


方式一:在项目根目录 gradle.properties 文件中配置

minSdk=21 targetSdk=31 compileSdk=31 javaMajor=11 javaVersion=11 compose=1.1.0-beta04 复制代码

方式二(推荐):在项目根目录 build.gradle.kts 中配置

// 这里是使用 version catalog 的写法,也可以直接替换成对应的版本号,参考方式一 ext {     set("minSdk", libs.versions.minSdk.get())     set("targetSdk", libs.versions.targetSdk.get())     set("compileSdk", libs.versions.compileSdk.get())     set("javaMajor", libs.versions.java.major.get())     set("javaVersion", libs.versions.java.asProvider().get())     set("compose", libs.versions.compose.get()) } 复制代码


这些都是必填项(compose 也是的,插件会默认添加对应版本的 compose 依赖和配置,如果实在不需要可以评论留言,后续版本可以加判断去掉)。

1.3 模块里应用

// 方式一(推荐),配合 version catalog 可以写成 alias(libs.plugins.config.plugin) plugins {     id("com.jady.lib.config-plugin") } // 方式二 apply(from = "com.jady.lib.config-plugin") 复制代码

添加完成后,一个 library 的配置文件将会非常简洁,只需要添加一些模块需要的插件和依赖就好了。

@file:Suppress("UnstableApiUsage") @Suppress("DSL_SCOPE_VIOLATION") plugins {     alias(libs.plugins.android.library)     alias(libs.plugins.hilt.android)     alias(libs.plugins.config.plugin) } dependencies {     // official library     implementation(libs.bundles.compose.core)     implementation(libs.hilt.runtime)     kapt(libs.bundles.hilt.compiler)     // other module     api(projects.framework.utils) } 复制代码


2 依赖管理

gradle 共享依赖官方文档:docs.gradle.org/current/use…

toml 官网:toml.io/en/

2.1 version catalog


以前,依赖的管理一直没有一种统一的方式,有的是通过设置进 project properties 中(比如建里一个 dependencies.gradle 文件管理),有的是建立一个插件工程,把所有的依赖都放插件里,这样有个好处就是这个插件可以多个项目共用,取的时候也是变量的形式来使用,version catalog 跟这种插件的形式比较像,只是 version catalog 是通用 toml 格式的文件来定义依赖的。

[versions] # build config compileSdk = "31" # official library kotlin = "1.6.0" compose = "1.1.0-beta04" androidx-appcompat = "1.4.0" [libraries] # official library appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" } androidx-activity-compose = "androidx.activity:activity-compose:1.4.0" compose-material = { module = "androidx.compose.material3:material3", version = "1.0.0-alpha02" } commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version = { strictly = "[3.8, 4.0[", prefer="3.9" } } [plugins] android-application = { id = "com.android.application", version.ref = "android-plugin" } [bundles] compose-core = ["androidx-activity-compose", "compose-uiTooling", "compose-material"] 复制代码

总结一下:

  1. gradle 支持四种节点:

    1. [versions] 用于定义版本号,版本号必须用字符串。

    2. [libraries] 用于定义依赖,支持的格式参考上面的例子

    3. [plugins] 用于定义插件

    4. [bundles] 用于定义依赖组

  2. 版本号支持指定单个版本和版本范围。具体规则可以参考 VersionConstraint 类的注释,也可以参考 Declaring Rich Versions,这里简单说明下:

    1. 版本范围用区间表示。() 表示开区间,[] 表示闭区间。[ 放在区间右边相当于 ),比如 [1, 2[ 相当于 [1, 2)]放在区间左边相当于 (,比如 ]1, 2] 相当于 (1, 2]

    2. 有四种版本匹配模式可以指定:strictlyrequirepreferreject

    3. require(不指定模式时,require 是默认模式)的版本或版本范围对应的是 VersionConstraint 中的 getRequiredVersion(),required version 表示最低支持的版本,可以更高,但不能比它低。

    4. strictly 表示严格要求的版本,字面意思,preferreject 也是字面意思。

定义的这些依赖可以本地用,也可以发布后使用。

2.2 本地使用


toml 文件位置没有规则,可自定义放置,一般放根目录 gradle 目录下,也可以放自己的配置文件目录,只要脚本文件中能引用到。现在可以定义 version catalog 容器了,参考:

dependencyResolutionManagement {     repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)     repositories {         mavenCentral()     }     versionCatalogs {         create("libs") {             from(files("${rootDir.path}/.config/dependencies-common.toml"))         }     } } 复制代码

sync 完之后会根据 toml 文件生成对应的 java 代码,你在 build.gradle 中已经能使用 libs 变量了。举个例子:

[versions] kotlin = "1.6.0" kotlin-coroutines = "1.6.0-RC2" [libraries] kotlin-stdlib-jdk7 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk7", version.ref = "kotlin" } [bundles] compose-core = ["androidx-activity-compose", "compose-uiTooling", "compose-material"] [plugins] kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } 对应的代码调用为: val kotlinVersion = libs.versions.kotlin.asProvider().get() val kotlinCoroutinesVersion = libs.versions.kotlin.coroutines.get() implementation(libs.kotlin.stdlib.jdk7) implementation(libs.bundles.compose.core) // 当前版本的 as 对 version catalog 支持不好,需要加下 @Suppress。 @Suppress("DSL_SCOPE_VIOLATION") plugins {     alias(libs.plugins.kotlin.android) } 复制代码

2.3 发布到仓库

发布代码:

@file:Suppress("UnstableApiUsage") @Suppress("DSL_SCOPE_VIOLATION") plugins {     `maven-publish`     `version-catalog` } catalog {     versionCatalog {         from(files("${rootDir.path}/.config/dependencies-common.toml"))     } } publishing {     publications {         create<MavenPublication>("maven") {             groupId = "com.jady.lib"             artifactId = "dependencies"             version = "1.0.0"             from(components["versionCatalog"])         }     }     repositories {         maven {             setUrl("repo.url")             credentials {                 username = project.property("repo.username").toString()                 password = project.property("repo.password").toString()             }         }     } } 复制代码

发布完后,更改上面提到的 dependencyResolutionManagement 即可。其他项目也可以通过这种方式共用依赖。

dependencyResolutionManagement {     versionCatalogs {         create("libs") {             from("com.mycompany:catalog:1.0")         }     } } 复制代码


3 插件工程


这里是的扩展属性是指这样的(BaseAppModuleExtension):

android {     compileSdk 30     defaultConfig {         applicationId "com.jady.sample"         minSdk 21         targetSdk 30         versionCode 1         versionName "1.0"         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"     }     buildTypes {         release {             minifyEnabled false             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'         }     }     compileOptions {         sourceCompatibility JavaVersion.VERSION_1_8         targetCompatibility JavaVersion.VERSION_1_8     }     kotlinOptions {         jvmTarget = '1.8'     } } 复制代码

多模块的时候,buildTypescompileOptions 这样的属性,每个模块都配置一遍倒是不算太麻烦的,麻烦的是每次修改的时候,每个模块都要改,这对于维护来说是非常不友好的。在插件里处理掉这些属性是比较好的一种做法。

我们先来创建一个插件项目。在创建之前,先讲下 Composing builds,虽然几年前就有了,但国内好像用的公司不多。那我这里来简单说下,Composing build 我个人更喜欢叫混合编译,也有翻译成复合构建或者组合构建的,我不管,我这里就叫混合编译????。

简单来说,混合编译的主要作用就是既可以让小模块作为独立工程编译运行,又可以作为大工程的一员一起编译运行。目前国内做编译加速的思路基本都是模块 aar 化,一个几十个模块的工程,针对没有改动的模块使用 aar 编译, 改动了的模块使用源码编译。实际上,如果模块比较独立,还可以更快一点,就是混合编译,单个模块做为独立工程开发调试,开发完之后啥也不用改,用大工程出包。

可以看我们插件的 master 分支。 image.png

注意插件是一个独立的工程,可以单独编译运行,可以切到插件源码 feature/plugin 分支查看。

所以这里的插件工程就是采用混合编译的形式,在主项目的 settings.gradle 文件中 includeBuild("plugins"),然后其他跟第一节讲的使用方式一样就可以了,是不是很神奇?即使我们在 pluginManagement 里设置了对应插件 id 的依赖地址,工程编译还是会使用我们的插件源码!当我们开发完毕,只需要发布新版,注释掉 includeBuild("plugins") 就好了。

下面来配置插件的 build.gradle

plugins {     `kotlin-dsl`     `maven-publish` } group = "com.jady.lib" version = "0.1.2" gradlePlugin {     plugins.register("config") {         id = "com.jady.lib.config-plugin"         implementationClass = "com.jady.lib.config.ConfigPlugin"     } } 复制代码


引入插件,设置 group 和 version,定义插件 id 和入口,就完成了。先不管插件怎么实现,看下怎么发布到 jitpack。切到  feature/plugin 分支,跑插件工程,jitpack 默认使用 java 1.8 编译,我们这里用的是 java 11,所以需要配置一下 jitpack,根目录添加 jitpack.yml,内容如下:

 jdk:   - openjdk11 复制代码

然后提交,给提交加个 tag,就可以在 jitpack 跑了(jitpack 地址),点击 Get it 会执行编译。

image.png

看日志文件最后的输出:

Build artifacts: com.github.Jadyli.composing:config-plugin:0.1.2 com.github.Jadyli.composing:com.jady.lib.config-plugin.gradle.plugin:0.1.2 复制代码

你会发现有两个,我们直接用第一个就好啦,具体参考第一节。

下面来写插件:

@Suppress("UnstableApiUsage") class ConfigPlugin : Plugin<Project> {     override fun apply(project: Project) {         project.run {             plugins.all {                 when (this) {                     is LibraryPlugin -> configureLibraryPlugin()                     is AppPlugin -> configureAppPlugin()                 }             }         }     }     private fun Project.configureLibraryPlugin() {         configCommonPlugin()         configCommonDependencies()         extensions.getByType<LibraryExtension>().configCommonExtension(this@configureLibraryPlugin)     }     private fun Project.configureAppPlugin() {         configCommonPlugin()         configCommonDependencies()         extensions.getByType<BaseAppModuleExtension>().run {             configCommonExtension(this@configureAppPlugin)             defaultConfig {                 splits {                     abi {                         isEnable = true                         reset()                         include("x86", "armeabi-v7a", "arm64-v8a")                         isUniversalApk = false                     }                 }             }             ...         }     }     private fun BaseExtension.configCommonExtension(project: Project) {         setCompileSdkVersion(project.property("compileSdk").toString().toInt())                  ...     }     private fun Project.configCommonPlugin() {         plugins.apply("org.jetbrains.kotlin.android")         ...     }     private fun Project.configCommonDependencies() {         ...     } } 复制代码


插件很简单,可以配置属性、插件、依赖,看代码都懂,没啥好说的,大家有需求可以评论,上面的 split 应该是有的项目用不了的,也可以根据自己的需求 fork 一份出来随意改。


作者:流沙三七
链接:https://juejin.cn/post/7041958178682044447

玩站网免费分享SEO网站优化 技术及文章 伪原创工具 https://www.237it.com/ 


文章分类
ANDROID
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐