一文了解Gradle 依赖管理(五)- 依赖管理缓存依赖

文章目录

  • 1. 版本目录 (Version Catalogs)
      • 1. 版本目录的概念与优势
      • 2. 主要优势
      • 3. 基本配置
      • 4. 使用版本目录
      • 5.使用外部版本目录文件
      • 6.实际项目中的版本目录最佳实践
  • 2. 依赖锁定(Dependency Locking)
      • 1. 依赖锁定的概念与重要性
      • 2. 主要优势
      • 3. 如何启用依赖锁定
      • 4. 生成锁定文件
      • 5. 更新锁定依赖
      • 6. 依赖锁定与版本目录结合使用
  • 3. 依赖缓存与离线构建
      • 1. Gradle 的依赖缓存机制
      • 2. 配置缓存位置
      • 3. 启用构建缓存
      • 4. 离线模式构建
      • 5. 依赖缓存的最佳实践

1. 版本目录 (Version Catalogs)

版本目录是 Gradle 7.0 引入的一项功能,它提供了一种集中管理依赖版本和依赖组的强大方式,尤其适合多模块项目。

1. 版本目录的概念与优势

版本目录是一种将依赖定义从构建脚本中抽离出来的机制,使依赖管理更加结构化、集中化,并支持更好的 IDE 支持。

2. 主要优势

1. 集中管理:在一个地方定义所有依赖版本和依赖组
2. 类型安全:提供类型安全的依赖访问,减少拼写错误
3. IDE 支持:更好的自动完成和导航支持
4. 依赖分组:按逻辑组织依赖
5. 版本控制:轻松更新和跟踪依赖版本变化

3. 基本配置

版本目录通常在 settings.gradlesettings.gradle.kts 文件中定义:

// 在settings.gradle中
dependencyResolutionManagement {versionCatalogs {libs {// 定义版本version('kotlin', '1.6.10')version('coroutines', '1.6.0')// 定义库library('kotlin-stdlib', 'org.jetbrains.kotlin', 'kotlin-stdlib').versionRef('kotlin')library('kotlin-reflect', 'org.jetbrains.kotlin', 'kotlin-reflect').versionRef('kotlin')library('coroutines-core', 'org.jetbrains.kotlinx', 'kotlinx-coroutines-core').versionRef('coroutines')// 定义依赖组(bundle)bundle('kotlin-bundle', ['kotlin-stdlib', 'kotlin-reflect'])// 定义插件plugin('kotlin-android', 'org.jetbrains.kotlin.android').versionRef('kotlin')}}
}

在 Kotlin DSL 中(settings.gradle.kts):

dependencyResolutionManagement {versionCatalogs {create("libs") {version("kotlin", "1.6.10")version("coroutines", "1.6.0")library("kotlin-stdlib", "org.jetbrains.kotlin", "kotlin-stdlib").versionRef("kotlin")library("kotlin-reflect", "org.jetbrains.kotlin", "kotlin-reflect").versionRef("kotlin")library("coroutines-core", "org.jetbrains.kotlinx", "kotlinx-coroutines-core").versionRef("coroutines")bundle("kotlin-bundle", listOf("kotlin-stdlib", "kotlin-reflect"))plugin("kotlin-android", "org.jetbrains.kotlin.android").versionRef("kotlin")}}
}

4. 使用版本目录

一旦定义了版本目录,我们就可以在构建脚本中使用它们:

plugins {id(libs.plugins.kotlin.android.get().pluginId)
}dependencies {implementation(libs.kotlin.stdlib)implementation(libs.coroutines.core)implementation(libs.bundles.kotlin.bundle)
}

5.使用外部版本目录文件

对于更复杂的项目,您可以将版本目录定义移动到专用的 TOML 文件中, 当然这也是Android官方推荐的做法,在新的AS项目中,默认就是使用的 TOML文件:

# libs.versions.toml
[versions]
kotlin = "1.6.10"
coroutines = "1.6.0"
retrofit = "2.9.0"
okhttp = "4.9.3"
room = "2.4.1"[libraries]
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
retrofit-core = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
retrofit-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
okhttp-core = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }[bundles]
kotlin = ["kotlin-stdlib", "kotlin-reflect"]
coroutines = ["coroutines-core", "coroutines-android"]
retrofit = ["retrofit-core", "retrofit-gson", "okhttp-core", "okhttp-logging"]
room = ["room-runtime"][plugins]
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" }

然后在 settings.gradle 中引用这个文件:

dependencyResolutionManagement {versionCatalogs {libs {from(files("libs.versions.toml"))}}
}

6.实际项目中的版本目录最佳实践

1. 按功能或技术栈分组:将依赖按照功能或技术栈分组,例如 networkuidatabase 等。
2. 使用有意义的别名:为依赖创建直观的别名,如 retrofit 而不是 squareup-retrofit
3. 充分利用版本引用:避免重复的版本号声明,使用版本引用确保相关库使用相同版本。
4. 创建有用的 bundle:将常一起使用的依赖组合成 bundle,简化依赖声明。
5. 保持 TOML 文件的良好组织:使用注释和分组保持文件可读性。

例如以下:

# 网络相关依赖
[libraries.retrofit]
module = "com.squareup.retrofit2:retrofit"
version = "2.9.0"# 注释说明特殊用途的依赖
[libraries.leak-canary]
module = "com.squareup.leakcanary:leakcanary-android"
version = "2.8.1"
# 仅在 debug 构建中使用

2. 依赖锁定(Dependency Locking)

依赖锁定是确保构建可重复性的重要技术,特别是当项目使用动态版本或版本范围时。

1. 依赖锁定的概念与重要性

依赖锁定将依赖图"冻结"在特定的时间点,记录解析的确切版本,确保后续构建使用相同的依赖版本,即使新版本发布。

2. 主要优势

  1. 构建可重现性:确保相同的源代码总是使用相同的依赖版本构建
  2. 防止意外升级:避免自动获取新发布的库版本
  3. 行为一致性:减少"在我的机器上能运行"问题
  4. 安全性:在审核新版本之前防止引入新依赖

3. 如何启用依赖锁定

settings.gradle 或特定项目的 build.gradle 中启用依赖锁定:

// 为所有配置启用依赖锁定
dependencyLocking {lockAllConfigurations()
}// 或者为特定配置启用
configurations.compileClasspath {resolutionStrategy.activateDependencyLocking()
}

4. 生成锁定文件

一旦启用了依赖锁定,您需要生成锁定文件:

# 为所有配置生成锁定文件
./gradlew dependencies --write-locks# 为特定项目生成锁定文件
./gradlew :app:dependencies --write-locks

这将在 gradle/dependency-locks 目录下创建锁定文件,每个配置一个文件。

5. 更新锁定依赖

当需要有意更新依赖版本时:

# 更新所有依赖锁
./gradlew dependencies --update-locks "com.squareup.retrofit2:*"# 或者完全刷新所有锁
./gradlew dependencies --write-locks

6. 依赖锁定与版本目录结合使用

依赖锁定和版本目录可以很好地结合使用,这种组合确保您既有集中的版本管理,又有确切的依赖锁定,提供最大的可重复性和控制。

  • 版本目录:声明您期望的依赖版本(理想状态)
  • 依赖锁定:记录实际解析的版本(实际状态)
// 在build.gradle中
dependencies {implementation libs.retrofit.core // 从版本目录
}dependencyLocking {lockAllConfigurations()
}

这里可能稍微难理解,我用个例子简单来描述一下。

假设我们开发的App中, Retrofit 2.9.0 依赖 OkHttp 4.9.0,但我们在版本目录中指定了更新的 OkHttp 4.9.3,

当没有依赖锁定时:

  • 第一个开发者构建项目时会使用 OkHttp 4.9.3
  • 下一个开发者几周后构建项目,可能 OkHttp 已更新到 4.9.5,他将使用 4.9.5

开启依赖锁定后:

  • 所有开发者都会使用锁定文件中的精确版本 OkHttp 4.9.3
  • 即使 OkHttp 发布了 4.9.5 版本,除非我们显式更新锁定文件,否则团队仍会使用 4.9.3

现在假设我们的目录版本中更新了Gson:

[versions]
# 更新了版本
gson = "2.9.0" # 从 2.8.5 更新

有了依赖锁定:

  1. 即使版本目录更新了,项目仍会使用锁定文件中的 2.8.5
  2. 团队可以讨论并决定何时更新锁定文件
  3. 当团队准备好时,可以显式更新锁定:
./gradlew dependencies --update-locks "com.google.gson*:*"

3. 依赖缓存与离线构建

有效管理依赖缓存可以显著提高构建性能,特别是在团队环境或 CI/CD 管道中。

1. Gradle 的依赖缓存机制

Gradle 在本地缓存所有下载的依赖,默认位置是用户主目录下的 .gradle/caches 目录。

2. 配置缓存位置

我们可以自定义缓存位置, 在 gradle.properties中:

# gradle.properties
org.gradle.caching=true
org.gradle.caching.debug=false
org.gradle.cache.dir=/custom/cache/directory

3. 启用构建缓存

构建缓存可以在配置中启用:

# settings.gradle
buildCache {local {enabled = true}
}

4. 离线模式构建

离线模式强制 Gradle 只使用缓存的依赖:

# 命令行参数
./gradlew build --offline# 或在 gradle.properties 中永久设置
org.gradle.offline=true

5. 依赖缓存的最佳实践

1. 共享缓存:考虑在团队之间或 CI 系统中共享缓存目录,减少重复下载

2. 定期清理:定期清理缓存,删除不再使用的依赖版本

./gradlew cleanBuildCache

3. 预热缓存:在 CI 构建前或开发环境设置中预热缓存

./gradlew downloadDependencies

4. 缓存备份:备份关键依赖的缓存,防止远程仓库不可用

5. 使用镜像或私有仓库:设置本地镜像或私有依赖仓库,减少外部依赖.

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

debug - 安装.msi时,为所有用户安装程序

文章目录 debug - 安装.msi时,为所有用户安装程序概述笔记试试在目标.msi后面直接加参数的测试 备注备注END debug - 安装.msi时,为所有用户安装程序 概述 为了测试,装了一个test.msi. 安装时,只有安装路径的选择,没…

Skyeye 云智能制造办公系统 VUE 版本 v3.15.14 发布

Skyeye 云智能制造,采用 Springboot winUI 的低代码平台、移动端采用 UNI-APP。包含 30 多个应用模块、50 多种电子流程,CRM、PM、ERP、MES、ADM、EHR、笔记、知识库、项目、门店、商城、财务、多班次考勤、薪资、招聘、云售后、论坛、公告、问卷、报表…

深度学习PyTorch之动态计算图可视化 - 使用 torchviz 生成计算图

序号系列文章1深度学习训练中GPU内存管理2深度学习PyTorch之数据加载DataLoader3深度学习 PyTorch 中 18 种数据增强策略与实现4深度学习pytorch之简单方法自定义9类卷积即插即用5深度学习PyTorch之13种模型精度评估公式及调用方法6深度学习pytorch之4种归一化方法(…

ZW3D二次开发_非模板表单_输入框类控件_逐字符回调

ZW3D的非模板表单的控件中有一些输入框类的控件,比如“ZsCc::LineEditBtn”,"ZsCc::LineEditEx"等,按照“ZW3D二次开发_非模板表单_控件_添加回调-CSDN博客”介绍的方法添加函数命令时,发现输入框在用户输入字符时不能动态地触发回…

Mysql--日志(错误日志、二进制日志、查询日志、慢查询日志)

四种日志对比总结 日志类型作用记录内容特点常见用途错误日志记录 MySQL 运行过程中的错误、警告及启动、关闭信息MySQL 系统错误、故障信息、警告等较少占用磁盘空间故障排查、系统监控二进制日志记录所有更改数据库数据的操作及事务执行情况DML、DDL 操作,不记录…

AI对软件工程(software engineering)的影响在哪些方面?

AI对软件工程(software engineering)的影响是全方位且深远的,它不仅改变了传统开发流程,还重新定义了工程师的角色和软件系统的构建方式。以下是AI影响软件工程的核心维度: 一、开发流程的智能化重构 需求工程革命 • …

ElementPlus 快速入门

目录 前言 为什么要学习 ElementPlus? 正文 步骤 1 创建 一个工程化的vue 项目 ​2 安装 element-Plus :Form 表单 | Element Plus 1 点击 当前界面的指南 2 点击左边菜单栏上的安装,选择包管理器 3 运行该命令 demo(案例1 ) 步骤 …

stable diffusion本地安装

1. 基本环境准备 安装conda 环境 pytorch基础学习-CSDN博客 创建虚拟环境: conda create -n sd python3.10 一定要指定用3.10,过高的版本会提示错误: 激活启用环境: conda activate sd 设置pip国内镜像源: pip conf…

使用 Go 构建 MCP Server

一个互联网技术玩家,一个爱聊技术的家伙。在工作和学习中不断思考,把这些思考总结出来,并分享,和大家一起交流进步。 一、MCP 介绍 1. 基本介绍 MCP(Model Context Protocol,模型上下文协议)是…

Python----计算机视觉处理(Opencv:模板匹配)

一、 概念 模板匹配就是用模板图(通常是一个小图)在目标图像(通常是一个比模板图大的图片)中不断的滑动 比较,通过某种比较方法来判断是否匹配成功。 二、应用场景 1. 目标检测与识别:在计算机视觉领域&am…

【stm32】用从模式控制器 完成PWM的测量

🌞学习视频还是来自于 铁头山羊 🌿主要是回顾一下他讲的这一章的定时器的部分,具体的话 还是看一下具体铁头山羊的视频,讲的很清楚~~ 整体流程是这样的,首先通过定时器的输出比较功能,配置好PA6产生一个特定…

【C#】CS学习之Modbus通讯

摘要 本文详细描述了如何在在C#的Winform应用程序中使用NModbus库实现Modbus通讯,包括读取保持寄存器、以及相应的UI界面设计和事件处理。 前言 ​应用场景 Modbus 从站广泛应用于工业自动化领域: 1、传感器数据采集(如温度、压力等&#xf…

Pycharm社区版创建Flask项目详解

一、创建工程项目 二、配置工程目录 新建的空项目下创建目录。 1、新建app.py文件 2、app.py代码如下: from flask import Flask, render_templateapp Flask(__name__)app.route("/") def root():"""主页:return: Index.html"&qu…

Linux 基础入门操作 第十二章 TINY Web 服务器

1 服务器基础架构 1.1 背景知识 Web 服务器使用 HTTP 协议与客户端(即浏览器)通信,而 HTTP 协议又基于 TCP/IP 协议。因此我们要做的工作就是利用 Linux 系统提供的 TCP 通信接口来实现 HTTP 协议。 而 Linux 为我们提供了哪些网络编程接口…

RAG优化:python从零实现[吃一堑长一智]循环反馈Feedback

本文将介绍一种有反馈循环机制的RAG系统,让当AI学会"吃一堑长一智",给传统RAG装了个"后悔"系统,让AI能记住哪些回答被用户点赞/拍砖,从此告别金鱼记忆: 每次回答都像在玩roguelike:失败结局会强化下次冒险悄悄把优质问答变成新知识卡牌,实现"以…

基于SpringBoot的名著阅读网站

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

[AI建模] 使用Pinokio本地化部署混元2D到3D AI建模服务

近年来,AI驱动的2D转3D建模技术发展迅猛,而Pinokio作为一个强大的AI模型管理与部署平台,使得在本地部署这些复杂的AI模型变得更加简单高效。本文将介绍如何使用Pinokio在本地部署混元2D到3D AI建模服务,并快速生成带或不带Texture的3D模型。 1. 在Pinokio Discover页面找到…

Qt 导入TagLib库

文章目录 0. 前言和环境介绍1. 下载TagLib2. 下载zlib3. 修改.pro文件4. 测试代码 0. 前言和环境介绍 最近在使用Qt写一个播放器,需要解析mp3文件,于是研究了一下如何导入TagLib库 Qt构建套件:Desktop Qt6.8.2 MinGW64-bit Qt Creator安装目录: D:\bit…

【前端面试题】计算机网络相关

总结面试前端过程可能会问到的计算机网络相关知识点 1.HTTP和HTTPS的区别 (1)HTTPS HTTP 安全加密 HTTPS 是 HTTP 的 加密版,通过 SSL/TLS 保障数据安全,防止窃听和篡改。 (2)HTTPS 如何保护数据&…

【RabbitMQ高级特性】消息确认机制、持久化、发送方确认、TTL和死信队列

🔥个人主页: 中草药 🔥专栏:【中间件】企业级中间件剖析 一、消息确认机制 消费者确认机制确保消息被正确处理后才从队列中删除。如果消费者处理失败(如业务异常或宕机),Broker 会重新投递消息…