Gradle统一管理依赖

背景

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

管理 Gradle 依赖

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

一、原始粗暴式

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

plugins {id 'com.android.application'id 'org.jetbrains.kotlin.android'
}android {compileSdk 33defaultConfig {applicationId "com.example.gradle"minSdk 21targetSdk 33versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility 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.compileSdkdefaultConfig {applicationId "com.example.gradle"minSdk versions.minSdktargetSdk versions.targetSdkversionCode versions.versionCodeversionName versions.versionNametestInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}kotlinOptions {jvmTarget = '1.8'}
}dependencies {implementation libraries.core_ktximplementation libraries.appcompatimplementation libraries.materialimplementation 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 = 33const val minSdk = 21const val targetSdk = 33const val versionCode = 1const 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.Versionsplugins {id 'com.android.application'id 'org.jetbrains.kotlin.android'
}android {compileSdk Versions.compileSdkdefaultConfig {applicationId "com.example.gradle"minSdk Versions.minSdktargetSdk Versions.targetSdkversionCode Versions.versionCodeversionName Versions.versionNametestInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}kotlinOptions {jvmTarget = '1.8'}
}dependencies {implementation Libraries.core_ktximplementation Libraries.appcompatimplementation Libraries.materialimplementation 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

在 Gradle 低版本中, 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')/*** 声明插件(在高版本的 Gradle 中才有)*/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 falsealias(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 falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}kotlinOptions {jvmTarget = '1.8'}
}dependencies {// 依赖单个指定的版本
//    implementation libs.coreKtx
//    implementation libs.appcompat
//    implementation libs.material
//    implementation libs.constraintlayout// 依赖项包implementation libs.bundles.appBaseLibimplementation libs.lifecycleExtensionsimplementation 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] 用于声明插件(Gradle 低版本不支持)

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://xiahunao.cn/news/2803486.html

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

相关文章

通过platform总线驱动框架编写LED灯的驱动,编写应用程序测试,发布到CSDN

效果图 设备树代码 myplatform{compatible "hqyj,myplatform";led1-gpio<&gpioe 10 0>;led2-gpio<&gpiof 10 0>;led3-gpio<&gpioe 8 0>; interrupt-parent <&gpiof>;interrupts<9 0>;reg<0X12345678 …

抖店商家想要抓住2024年第一波流量,你需要这样做!

大家好&#xff0c;我是电商小布。 春节假期结束了&#xff0c;我们的工作也开始走入正轨当中了。 对于停工一段时间的抖店商家来说&#xff0c;想要在年后抓住第一波流量&#xff0c;该怎么做呢&#xff1f; 简单一点说&#xff0c;还是在运营上。 一、检查店铺类目情况 …

数字电路 第一章—第三节(逻辑函数的化简方法)

一、逻辑函数的标准与或式和最简式 1、标准与或表达式 &#xff08;1&#xff09;下图给出了逻辑函数Y的标准与或表达式&#xff0c;在表达式中每一个乘积项都具有标准形式&#xff0c;这种标准形式的乘积项称为最小项。 &#xff08;2&#xff09;最小项是逻辑代数中的一个…

Windows 2008部署

创建虚拟机2008 创建之后实现远程连接 后端部署 然后解压jdk tomcat mysql jdk 配置环境变量 修改JAVA_HOME 变量名&#xff1a;JAVA_HOME 变量值&#xff1a;电脑上JDK安装的绝对路径 修改CLASSPATH 变量名&#xff1a;CLASSPATH 变量值&#xff1a;.;%JAVA…

vue2+element医院安全(不良)事件报告管理系统源代码

目录 安全不良事件类型 源码技术栈 医院安全&#xff08;不良&#xff09;事件报告管理系统采用无责的、自愿的填报不良事件方式&#xff0c;有效地减轻医护人员的思想压力&#xff0c;实现以事件为主要对象&#xff0c;可以自动、及时、实际地反应医院的安全、不良、近失事件…

力扣经典题目解析--旋转图像(字节二面)

题目 原题地址: . - 力扣&#xff08;LeetCode&#xff09; 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1…

基础软件之道:企业级实践与开源创新【文末送书-22】

文章目录 前言-基础软件之路&#xff1a;企业级实践及开源之路企业级实践1. 高可用性和容错性2. 安全性和隐私保护3. 自动化和DevOps实践 开源之路1. 开源操作系统2. 容器化和编排工具3. 数据库系统4. 自动化工具 基于编译器的静态代码分析与软件开发效率、质量和性能1、静态分…

Sora还太远!国产AI创作恐怖电影:《生化危机:重生》上

Sora用不上&#xff01;国产AI创作恐怖电影&#xff1a;《生化危机&#xff1a;重生》上 丧尸围城&#xff0c;世界沦陷&#xff0c;爱丽丝是拯救这个世界的最后一剂解药&#xff0c;然而。。。 《生化危机&#xff1a;重生》&#xff08;上&#xff09;电影开始地球已经被丧尸…

最长的回文串

开始想的简单了&#xff0c;确实没想到奇数字母删去一个后也能用 解法&#xff1a; 桶排序 #include<iostream> #include<vector> #include<algorithm> using namespace std; #define endl \n #define int long long signed main() {int t;cin >> t…

前后端分离vscode保险业务管理系统vue+Nodejs

本设计主要应用于完成对保险业务进行计算机化的管理。系统前台展示各种种类的保险&#xff0c;顾客可以选择登陆后买入。公司员工为管理员&#xff0c;由公司统一分配账号&#xff0c;员工用工号密码登陆。可以修改密码&#xff0c;查看、修改自己的信息。员工可处理顾客信息。…

Qt 事件

1. 事件 事件是对各种应用程序需要知道的由应用程序内部或者外部产生的事情或者动作的通称。在Qt中使用一个对象来表示一个事件&#xff0c;它继承自QEvent类。 2. 事件和信号 事件与信号并不相同&#xff0c;比如我们使用鼠标点击了一下界面上的按钮&#xff0c;那么就会产生…

DT DAY3 信号和槽

作业&#xff1a; 1> 思维导图 2> 使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 btn3 new QPushButton("按钮3",this);btn3->resize(ui->btn2->width(),ui->b…

【Spring】Spring MVC

目 录 一.什么是 Spring MVC&#xff1f;1.MVC 定义2.MVC 和 Spring MVC 的关系 二.为什么要学 Spring MVC&#xff1f;三.怎么学 Spring MVC&#xff1f;1.Spring MVC 创建和连接综上连接方式&#xff1a; 2.获取参数1.传递单个参数2.获取多个参数3.获取对象4.获取表单参数5.接…

基于springboot+vue的桂林旅游景点导游平台(前后端分离)

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

Pyglet综合应用|推箱子游戏之关卡图片载入内存

目录 读取图片 分割图片 综合应用 本篇为之前写的博客《怎样使用Pyglet库给推箱子游戏画关卡地图》的续篇&#xff0c;内容上有相关性&#xff0c;需要阅读的请见链接&#xff1a; https://hannyang.blog.csdn.net/article/details/136209138 「推箱子」是一款风靡全球的益…

RabbitMQ学习整理————基于RabbitMQ实现RPC

基于RabbitMQ实现RPC 前言什么是RPCRabbitMQ如何实现RPCRPC简单示例通过Spring AMQP实现RPC 前言 这边参考了RabbitMQ的官网&#xff0c;想整理一篇关于RabbitMQ实现RPC调用的博客&#xff0c;打算把两种实现RPC调用的都整理一下&#xff0c;一个是使用官方提供的一个Java cli…

开源博客项目Blog .NET Core源码学习(9:Autofac使用浅析)

开源博客项目Blog使用Autofac注册并管理组件和服务&#xff0c;Autofac是面向.net 的开源IOC容器&#xff0c;支持通过接口、实例、程序集等方式注册组件和服务&#xff0c;同时支持属性注入、方法注入等注入方式。本文学习并记录Blog项目中Autofac的使用方式。   整个Blog解…

NXP实战笔记(六):S32K3xx基于RTD-SDK在S32DS上配置PWM发波

目录 1、概述 2、SDK配置 2.1、Port配置 2.2、Emios_Mcl_Ip 2.3、Emios_Pwm 2.4、代码示例 1、概述 针对S32K3xx芯片&#xff0c;产生PWM的硬件支持单元仅有两个&#xff0c;分别是eMiosx与Flexio. 生成PWM的顺序&#xff0c;按照单片机所用资源进行初始化执行如下 初始化…

UTONMOS开启数智龙年,打造元宇宙游戏圈新名片

新年已过&#xff0c;全国各个城市早已客流涌动、热闹非凡。这种繁华景象不仅存在于现实世界&#xff0c;也被复刻到元宇宙的虚拟空间中。 据介绍&#xff0c;UTONMOS“源起山海-神念无界”元宇宙游戏是以原创IP玄幻神话故事“元宇宙史纪”为蓝本打造的元宇宙游戏空间&#xf…

【DataTable.js】02.DataTable参考

一、Option 1.1 Features 属性类型默认值描述autoWidthbooleantrue是否自动调节单元格宽度&#xff0c;若传入了columns.width&#xff0c;可禁用该选项orderingbooleantrue是否支持排序pagingbooleantrue是否支持分页scrollXbooleanfalse是否支持横向滚动条scrollYstring启用…