Gradle统一管理依赖

news2024/12/26 11:16:00

背景

随着项目越来越大,module 越来越多,依赖的库也越来越多,依赖管理也越来越混乱。
我们一般会有以下需求:
1.  项目依赖统一管理,在单独文件中配置
2.  不同 Module 中的依赖版本号统一

管理 Gradle 依赖

说明:下面所有示例都是基于 Gradle 7.3.0 版本

一、原始粗暴式

在 module 的 build.gradle 中直接引入,就像下面代码一样

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    compileSdk 33
    defaultConfig {
        applicationId "com.example.gradle"
        minSdk 21
        targetSdk 33
        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'
    }
}

dependencies {
    implementation 'androidx.core:core-ktx:1.9.0'
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.6.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
}

优点:方便快捷,依赖的时候复制粘贴一气呵成

缺点:多模块中可能会存在不同版本的依赖,进行版本升级的时候改动非常麻烦。

二、ext 式

Gradle 提供了 ext 关键字可以让我们去定义自身所需要的扩展属性,我们可以通过 ext 关键字对我们工程中的依赖进行全局配置。

1. 直接在 project 的 build.gradle 中编写 ext 。

ext {
    versions = [
            compileSdk      : 33,
            minSdk          : 21,
            targetSdk       : 33,
            versionCode     : 1,
            versionName     : "1.0.0",

            core_ktx        : "1.9.0",
            appcompat       : "1.6.1",
            material        : "1.6.1",
            constraintlayout: "2.1.4"
    ]

    libraries = [
            core_ktx        : "androidx.core:core-ktx:${versions.core_ktx}",
            appcompat       : "androidx.appcompat:appcompat:${versions.appcompat}",
            material        : "com.google.android.material:material:${versions.material}",
            constraintlayout: "androidx.constraintlayout:constraintlayout:${versions.constraintlayout}"
    ]
}

在 module 的 build.gradle 中的使用如下 

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    compileSdk versions.compileSdk
    defaultConfig {
        applicationId "com.example.gradle"
        minSdk versions.minSdk
        targetSdk versions.targetSdk
        versionCode versions.versionCode
        versionName versions.versionName
        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'
    }
}

dependencies {
    implementation libraries.core_ktx
    implementation libraries.appcompat
    implementation libraries.material
    implementation libraries.constraintlayout
}

这样,所有的 module 需要更新依赖库版本的时候,去修改 ext 下的代码即可

2. 在另一个 gradle 脚本中进行编写 ext

随着依赖项越来越多,ext 中的代码也越来越庞大,为了更好地管理。我们会把代码写在一个 .gradle ( config.gradle )文件中。

 config.gradle 中的代码如下

ext {
    versions = [
            compileSdk      : 33,
            minSdk          : 21,
            targetSdk       : 33,
            versionCode     : 1,
            versionName     : "1.0.0",

            core_ktx        : "1.9.0",
            appcompat       : "1.6.1",
            material        : "1.6.1",
            constraintlayout: "2.1.4"
    ]

    libraries = [
            core_ktx        : "androidx.core:core-ktx:${versions.core_ktx}",
            appcompat       : "androidx.appcompat:appcompat:${versions.appcompat}",
            material        : "com.google.android.material:material:${versions.material}",
            constraintlayout: "androidx.constraintlayout:constraintlayout:${versions.constraintlayout}"
    ]
}

在 project 的 build.gradle 中的中引用 config.gradle 文件,方式如下图:

在 module 的 build.gradle 中的使用不变

优点:依赖的版本统一管理,版本升级只用修改config.gradle 文件中的 ext 属性。

缺点: 在 module 的 build.gradle 中使用时,不支持代码提醒,不支持点击跳转,多 moudle 开发时,不同 module 的依赖需要 ctrl+c/v 导致开发的效率降低

三、kotlin+buildSrc式

ext 可以帮我们很好地解决了管理依赖的问题,美中不足的是它不支持点击跳转、自动补全的问题。这就轮到 buildSrc 大显身手了。

运行 gradle 时,它首先会检查项目中是否存在一个叫 buildSrc 的目录,如果有的话,gradle 会自动编译并测试这段代码,并将其放入构建脚本的类路径中。

  1. 在 project 的根目录下创建 buildSrc 目录

  2. 在 buildSrc 中新建 build.gradle 文件

    apply plugin: 'kotlin'
    
    buildscript {
        // 这里保持与主工程版本一致
        ext.kotlin_version = '1.7.20'
        repositories {
            mavenCentral()
            google()
        }
        dependencies {
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        }
    }
    
    repositories {
        mavenCentral()
        google()
    }
  3. 在 buildSrc 中创建 /src/main/kotlin目录,然后在新建 com.gradle 包名,最后创建 Dependencies.kt 文件

     4. Dependencies.kt 中编写依赖管理的代码,如下

object Versions {
    const val compileSdk = 33
    const val minSdk = 21
    const val targetSdk = 33
    const val versionCode = 1
    const val versionName = "1.0.0"

    const val core_ktx = "1.9.0"
    const val appcompat = "1.6.1"
    const val material = "1.6.1"
    const val constraintlayout = "2.1.4"
}

object Libraries {
    const val core_ktx = "androidx.core:core-ktx:${Versions.core_ktx}"
    const val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}"
    const val material = "com.google.android.material:material:${Versions.material}"
    const val constraintlayout = "androidx.constraintlayout:constraintlayout:${Versions.constraintlayout}"
}

     5. 在 module 的 build.gradle 中使用如下 

import com.gradle.Libraries
import com.gradle.Versions

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    compileSdk Versions.compileSdk
    defaultConfig {
        applicationId "com.example.gradle"
        minSdk Versions.minSdk
        targetSdk Versions.targetSdk
        versionCode Versions.versionCode
        versionName Versions.versionName
        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'
    }
}

dependencies {
    implementation Libraries.core_ktx
    implementation Libraries.appcompat
    implementation Libraries.material
    implementation Libraries.constraintlayout
}

 使用时 Android Stuido 自动提示如下

优点:这种方式支持 IDE 输入代码会有提示,会自动完成,并且支持 AndroidStudio 单击跳转。

缺点:依赖更新将重新构建整个项目,对编译速度有一定的影响。而且 buildSrc 是编译期才生效,并且其生命周期在project 的 build.gadle 执行之后,所以没办法把插件相关的配置给维护起来。

四、Verison Catalogs 管理

4.1 Version Catalogs 特点

  • 对所有 module 可见,可统一管理所有 module 的依赖,Gradle 会为每个依赖目录生成一个类型安全的访问器,同时可以管理 project 的 build.gradle 中的插件依赖。

  • 依赖项除了可以声明为单个依赖目录,还可以将多个依赖项声明为依赖目录组。即支持声明依赖bundles, 即总是一起使用的依赖可以组合在一起,

  • 支持版本号与依赖名分离,可以在多个依赖间共享版本号

  • 支持在单独的 libs.versions.toml 文件中配置依赖

  • 支持在项目间共享依赖

4.2 启用 Version Catalogs

在 AGP 低版本中, Version Catalogs 属于孵化中的特效,使用它之前需要启用该特性。

在 settings.gradle 中添加如下代码:

pluginManagement {
    ...
}

enableFeaturePreview("VERSION_CATALOGS")

dependencyResolutionManagement {
   ...
}

...

4.3 使用 Version Catalogs

在 settings.gradle 中声明,如下:

...
dependencyResolutionManagement {
    ...
    // 编写版本目录的依赖库
    versionCatalogs {
        libs {
            // 版本
            version('compileSdk', '33')
            version('minSdk', '21')
            version('targetSdk', '33')
            version('versionCode', '1')
            version('versionName', '1.0.0')

            /**
             * 声明依赖
             * 例如:别名('coreKtx')、groupId('androidx.core')、artifactId('core-ktx')以及版本('1.9.0')
             * alias 在AGP的低版本中使用,高版本中使用 library
             */
            // alias('coreKtx').to('androidx.core', 'core-ktx').version('1.9.0')
            library('coreKtx', 'androidx.core', 'core-ktx').version('1.9.0')
            library('appcompat', 'androidx.appcompat', 'appcompat').version('1.6.1')
            library('material', 'com.google.android.material', 'material').version('1.6.1')
            library('constraintlayout', 'androidx.constraintlayout', 'constraintlayout').version('2.1.4')


            // 除了单个依赖声明,我们也可以将多个依赖项声明为一个依赖组
            bundle('appBaseLib', ['coreKtx', 'appcompat', 'material', 'constraintlayout'])

            // 针对多个相同版本号的依赖,我们可以定一个通用版本号,即将依赖与版本单独声明并引用
            version('lifecycle', '2.2.0')
            library('lifecycleExtensions', 'androidx.lifecycle', 'lifecycle-extensions').versionRef('lifecycle')
            library('lifecycleRuntimeKtx', 'androidx.lifecycle', 'lifecycle-runtime-ktx').versionRef('lifecycle')

            /**
             * 声明插件(在高版本的AGP中才有)
             */
            plugin('androidApplication', 'com.android.application').version('7.3.0')
            plugin('kotlinAndroid', 'org.jetbrains.kotlin.android').version('1.7.20')
        }
    }
}

...

在 project 的 build.gradle 中的使用如下

plugins {
//    id 'com.android.application' version '7.3.0' apply false
//    id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
    /* 依赖插件 等同于上面注释掉的代码 */
    alias(libs.plugins.androidApplication) apply false
    alias(libs.plugins.kotlinAndroid) apply false
}

在 module 的 build.gradle 中的使用如下

plugins {
//    id 'com.android.application'
//    id 'org.jetbrains.kotlin.android'
    /* 依赖插件 等同于上面注释掉的代码 */
    alias(libs.plugins.androidApplication)
    alias(libs.plugins.kotlinAndroid)
}

android {
    compileSdk libs.versions.compileSdk.get().toInteger()
    defaultConfig {
        applicationId "com.example.gradle"
        minSdk libs.versions.minSdk.get().toInteger()
        targetSdk libs.versions.targetSdk.get().toInteger()
        versionCode libs.versions.versionCode.get().toInteger()
        versionName libs.versions.versionName.get()
        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'
    }
}

dependencies {
    // 依赖单个指定的版本
//    implementation libs.coreKtx
//    implementation libs.appcompat
//    implementation libs.material
//    implementation libs.constraintlayout

    // 依赖项包
    implementation libs.bundles.appBaseLib
  
    implementation libs.lifecycleExtensions
    implementation libs.lifecycleRuntimeKtx

}

这种方式支持 IDE 输入代码会有提示,会自动完成,并且支持 AndroidStudio 单击跳转。但是这种方式会导致 settings.gradle 非常臃肿

通过 toml 文件声明 version catalogs

除了在 settings.gradle 文件中直接声明依赖目录,官方更推荐使用 toml 文件来声明依赖目录,而且在 toml 中编写代码时 Android Studio 会有提示,非常的方便。

首先在项目根目录下创建 libs.versions.toml 文件,文件名可以任意取,并编写如下依赖内容:

[versions]
agp = "7.3.0"
kotlin = "1.7.20"
compileSdk = "33"
minSdk = "21"
targetSdk = "33"
versionCode = "1"
versionName = "1.0.0"

coreKtx = "1.9.0"
appcompat = "1.6.1"
material = "1.6.1"
constraintlayout = "2.1.4"
lifecycle = "2.2.0"

[libraries]
coreKtx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
material = { module = "com.google.android.material:material", version.ref = "material" }
constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }
lifecycleExtensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "lifecycle" }
lifecycleRuntimeKtx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle" }

[bundles]
appBaseLib = ["coreKtx", "appcompat", "material", "constraintlayout"]

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

toml 文件的使用说明

1. toml 文件由 4个主要部分组成

[versions] 用于声明可以被依赖项引用的版本

[libraries] 用于声明依赖的别名

[bundles] 用于声明依赖包(依赖组)

[plugins] 用于声明插件(AGP低版本不支持)

2. 声明 libraries 时,可以使用

coreKtx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }

或者

coreKtx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }

随后在 setting.gradle 中引用该 toml 文件

...
dependencyResolutionManagement {
    ...
    // 编写版本目录的依赖库
    versionCatalogs {
        libs {
            from(files("./libs.versions.toml"))
        }
    }
}

...

在 module 的 build.gradle 中的使用方式不变。

注意:Version Catalogs 中变量命名大小写敏感,且以小写字母开头, 命名中可以如包含 “-” 或者 “_” 或者 “.” ,在相当于分组了。

举例说明:

lifecycle_runtime_ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle" }

在使用时

implementation libs.lifecycle.runtime.ktx

4.4 发布到远端

如果你没有共享依赖的需求,那么上面的方式已经足够使用了。

但是现在基本上都是组件化开发了,特别是当组件数量比较多或者公司内有其他 App 时,大概率就会有统一依赖版本以及共享依赖的需求了。那我们可以把 Version Catalog 发布到远端,其他项目需要时直接依赖然后使用即可,这样就很方便的实现了版本的统一以及快速依赖了。毕竟拷贝来拷贝去非常麻烦且不好维护。

Version Catalog发布也比较简单,按照 官方文档 来即可。

总结

Android 发展至今,各种新技术层出不穷,版本管理也出现了很多方案,这些方案并没有绝对的优劣,还是需要结合实际项目需求来选择的,但是新的方案还是需要学习了解的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1460496.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3学习——标签的ref属性

在HTML标签上&#xff0c;可以使用相同的ref名称&#xff0c;得到DOM元素ref放在组件上时&#xff0c;拿到的是组件实例&#xff08;组件defineExpose暴露谁&#xff0c;ref才可以看到谁&#xff09; <script setup lang"ts"> import RefPractice from /compo…

C++/C函数指针及函数指针数组

文章目录 什么是函数指针函数指针的使用为什么要使用函数指针&#xff1f;回调函数函数指针数组及使用阅读两段有趣的代码指向成员函数的指针&#xff08;C特有&#xff09; 什么是函数指针 首先它是一个指针&#xff0c;一个指向函数的指针&#xff0c;在内存空间中存放的是函…

Camunda快速入门(五):设计一个带DMN业务规则的流程

接上一篇文章&#xff1a;Camunda快速入门&#xff08;四&#xff09;&#xff1a;设计一个带网关的流程 在本节中&#xff0c;您将学习如何使用 BPMN 2.0 业务规则任务和 DMN 1.3 决策表将决策自动化添加到流程中。 1、将业务规则任务添加到流程 使用 Camunda Modeler 打开…

Python学习-if else及比较运算符、while循环结构、random生成随机数模块

五、if else及比较运算符 1、if else语法 if 条件&#xff1a; 如果条件为真&#xff08;Ture&#xff09;执行这里的语句 else: 如果条件为假&#xff08;False&#xff09;执行这里的语句 2、比较运算符 运算符含义<判断左边是否小于右边<判断左边是否小于或等于右…

《nvm 安装》nodejs 版本管理工具

一.前言 如果先于 nvm 安装了 node&#xff0c;一定要先卸载&#xff01; 两种卸载方式&#xff1a; 方式一 控制面板 -> 程序和功能 -> nodejs 删除 方式二 下载的 node 安装包有卸载选项 二. 安装 nvm 下载地址 中找到对应的安装包&#xff0c;我本机使用 window…

关于公司私有gitlab拉去项目中遇到的问题

新进公司都会遇到拉去项目代码问题&#xff0c;新账号新环境&#xff1b;怎么拉去代码才是最有效的呢&#xff1f; 在此某些大神会给你一个地址&#xff1a;一句你自己来取吧&#xff1b;拉下来看看逻辑就行了&#xff1b;这样的人挺不错&#xff1b;会让你陷入无限的BUG循环中…

安卓adb调试备忘录

由于 MAC 的 USB 口全被占用着&#xff0c;采用无线连接刚方便&#xff0c;记录一下&#xff0c;以防忘记~ ADB原理 adb devices -l ## 列出连接的设备adb tcpip [端口号] adb tcpip 6666 # 将当前已连接USB上的Mobile端切换为TCP/IP模式&#xff0c;以6666端口进行监听. adb…

数字孪生与智慧城市:共筑未来城市的科技基石

一、引言 随着科技的飞速发展&#xff0c;数字孪生与智慧城市已成为未来城市建设的两大关键技术。数字孪生为城市提供了一个虚拟的数字镜像&#xff0c;使我们能全面、深入地了解城市的运行状态。而智慧城市则借助先进的信息通信技术&#xff0c;提升城市的智能化水平&#xf…

机器学习基础(三)监督学习的进阶探索

导语&#xff1a;上一节我们深入地探讨监督学习和非监督学习的知识&#xff0c;重点关注它们的理论基础、常用算法及实际应用场景&#xff0c;详情可见&#xff1a; 机器学习基础&#xff08;二&#xff09;监督与非监督学习-CSDN博客文章浏览阅读769次&#xff0c;点赞15次&a…

明御运维审计与风险控制系统漏洞复现

简介 明御运维审计与风险控制系统是安恒信息在多年运维安全管理的理论和实践经验积累的基础上,采用B/S架构,集“身份认证、账户管理、控制权限、日志审计”于一体,支持多种字符终端协议、文件传输协议、图形终端协议、远程应用协议的安全监控与历史查询,具备全方位运维风险…

springboot+vue的飘香水果购物网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

JavaScript 设计模式之组合模式

组合模式 在我们日常中肯呢个会将一个表单用这种模式来创建 const Car function () { } Car.prototype.getName function () { throw new Error("需要重写该方法") } Car.prototype.getPrice function () {throw new Error("需要重写该方法") } const…

05_i2c_controller内核模块

01_basicLinux内核模块-CSDN博客文章浏览阅读304次&#xff0c;点赞3次&#xff0c;收藏3次。环境IDubuntuMakefilemodules:clean:basic.creturn 0;运行效果。https://blog.csdn.net/m0_37132481/article/details/136157384i2c_controller.c rootT:/media/sf_D_DRIVE/kmodule/…

书生·浦语大模型实战营第五节课作业

基础作业 本地部署300字的小故事在这里插入图片描述

Easyx的学习1

使用easys的相关函数需要包含头文件#include<easyx.h>或#include<graphics.h>&#xff08;#include<graphics.h>包含了<easyx.h>和一些不推荐使用的函数&#xff09; 目录 窗口创建背景颜色 基本图形绘制 1.点 2.线 3.矩形 圆角矩形 4. 圆形 椭圆…

一文彻底搞懂Java对象什么时候被垃圾器回收

文章目录 1. 简介2. 引用计数法2.1 优点2.2 缺点 3. 可达性分析算法3.1 虚拟机栈&#xff08;栈帧中的本地变量表&#xff09;中引用的对象3.2 方法区中静态属性引用的对象3.3 方法区中常量引用的对象3.4 本地方法栈中 JNI&#xff08;即一般说的 Native 方法&#xff09;引用的…

Day23--learning English

一、积累 1.straw 2.umami | tangy | bland 3.lactose dairy 4.fatigue 5.stumble | curb 6.pore 7.toll 8.arrear 9.robe 10.stylish 11.dash 12.mischief 13.ranch 14.sponsorship 15.podcast 16.villian 17.clutch 18.envision 二、练习 1.牛津原译 1.straw /strɔː/ 1…

ngnix网站服务详解

一 Nginx的简介 1 Nginx&#xff1a; ①Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器&#xff0c;而且支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件版本进行热…

11 个适用于 Windows电脑的最佳免费录制屏幕软件(2024)

屏幕录制软件可让您捕获屏幕以与他人共享并创建与产品相关的视频、教程、课程、演示、网络视频等。该软件使您能够从网络摄像头和屏幕录制视频。 11 个适用于 Windows电脑的最佳免费屏幕录像机 以下是精心挑选的顶级屏幕录像机列表&#xff0c;及其受欢迎的功能和网站链接。该…

Spring Boot与Feign:微服务架构下的优雅通信

1. 前言 本文将详细介绍在Spring Boot框架中如何使用Feign进行微服务之间的优雅通信。我们将从Feign的基本原理讲起&#xff0c;然后逐步展开使用Feign的完整流程和步骤&#xff0c;包括代码示例和详细注释。通过本文&#xff0c;读者将能够轻松掌握Feign在Spring Boot微服务架…