新一代版本依赖管理Vesion Catalog的探索与实践

news2024/9/28 23:36:49

前言

前段时间使用新版本的Android Studio创建了个项目想测试点东西,项目创建后发现整个Gradle的依赖管理发生了巨大的变化。
先说一下我使用的Android Studio的版本如下。
在这里插入图片描述
创建项目后主要变化如下:

  1. 原本的.gradle变成了.gradle.kts,也就是说以后肯定是以kts脚本为主了。kts相较于grovvy使用起来更加方便,语言统一,且有提示。
  2. AGP版本升到了8+
  3. 版本依赖变成了下面这个样子
    在这里插入图片描述
    点击依赖发现会跳转到 gradle目录下的libs.versions.toml 文件内
    在这里插入图片描述

这个libs.version.toml实际上是Gradle新版本提供的一种依赖管理方式,详情可以看 version catalog 官方文档

在version catalog 之前,实际上在Android中的Gradle依赖管理还有以下几种方式

  1. 直接依赖 最原始的方式,维护依赖版本时很麻烦
  2. 在ext中声明依赖的信息,然后在依赖处使用ext中声明的变量进行依赖管理,初步解决了依赖版本统一的问题,但写起来没提示,还是很麻烦
  3. 通过内置的buildSrc插件进行依赖管理,在插件内部通过代码维护依赖信息,使用依赖时导包使用即可,本质上就是个静态变量的方式。这种方式算是比较友好了,写依赖的时候有提示,在编译期会进行校验,由于每次更改都会导致全量编译,因此对编译速度有一定的影响。
  4. 使用Include build,可以像buildSrc那样把依赖信息维护在代码内,使用时也跟跟buildSrc类似,但是编译速度要更快,也有提示以及点击跳转等功能。

前面几种方式我都用过,在version catalog出来之前的很长一段时间我用的都是Include build这种方式,但是其还有一个问题没法解决就是根目录下的插件版本没办法管理到,如图所示,例如我希望把therouter的插件版本也管理起来,因为他的版本我已经在com.yzq.dependency-manager中声明过了。
在这里插入图片描述
但是不管是buildSrc还是Include build,都是编译期才生效,并且其生命周期也都在根目录build.geadle执行之后,所以没办法把插件相关的配置给维护起来。

而 Vesion Catalog 就解决了这个问题。

Vesion Catalog的使用和发布

Version Catalog的使用非常简单,官方文档介绍的已经非常详细了,推荐直接去看 官方文档 即可。
需要注意的是使用Version Catalog对Gradle的版本是有要求的,推荐直接在AGP8以上的版本使用,没有什么奇怪的限制。

这里我门快速过一下使用方式

方式一

直接在settings.gradle.kts中声明versionCatalogs以及相关的配置信息即可

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
     
    }
    versionCatalogs {
    
        create("androidLibs") {
            /*声明版本号*/
            version("minSdk", "21")
            version("compileSdk", "33")
            version("targetSdk", "33")
            version("kotlin", "1.8.22")
            /**
             * 声明依赖库
             *  方式一:别名, 依赖库的具体坐标和版本
             *  方式二:别名, group,artifact,version
             */
            library("androidx-appcompat", "androidx.appcompat:appcompat:1.3.1")//方式一
            library("androidx-core-ktx", "androidx", "core:core-ktx").version("1.6.0")//方式二
            /*把依赖库打包 一起依赖*/
            bundle("androidx", listOf("androidx-appcompat", "androidx-core-ktx"))
            /*声明插件*/
            plugin("android-library", "com.android.library").version("8.0.2")
            plugin("kotlin-android", "org.jetbrains.kotlin.android").versionRef("kotlin")
        }


    }
}

随后使用方式如下:

plugins {
//    id("com.android.library")
//    id("org.jetbrains.kotlin.android")
	/*依赖插件 等同于上面注释掉的代码*/
    alias(androidLibs.plugins.android.library)
    alias(androidLibs.plugins.kotlin.android)
}

android {
    namespace = "com.yzq.mylibrary2"
    compileSdk = androidLibs.versions.compileSdk.get().toInt()
}

dependencies {
    /*单独依赖*/
    implementation(androidLibs.androidx.core.ktx)
    implementation(androidLibs.androidx.appcompat)
    /*打包依赖*/
    implementation(androidLibs.bundles.androidx)
}

在添加依赖时是有提示的,同时把插件的版本也管理起来了。

方式二

方式二是官方推荐的方式,就是在toml文件中管理依赖。创建新项目时默认就是这种方式,默认的文件路径在文章开头也给出了,是在gradle文件夹里。
在这里插入图片描述

至于写法也很简单,这里不赘述了。

  • [versions]就是声明版本的
  • [libraries]就是声明依赖库的
  • [plugins]就是声明插件的
  • [bundles]就是打包依赖,用来简化依赖

示例如下:

[versions]
agp = "8.2.0-alpha10"
kotlin = "1.8.21"
core-ktx = "1.9.0"
junit = "4.13.2"
androidx-test-ext-junit = "1.1.5"
espresso-core = "3.5.1"
appcompat = "1.6.1"
material = "1.9.0"
constraintlayout = "2.1.4"
lifecycle-livedata-ktx = "2.6.1"
lifecycle-viewmodel-ktx = "2.6.1"
navigation-fragment-ktx = "2.6.0"
navigation-ui-ktx = "2.6.0"

[libraries]
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" }
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" }
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle-livedata-ktx" }
lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle-viewmodel-ktx" }
navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigation-fragment-ktx" }
navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigation-ui-ktx" }

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

[bundles]
androidX = { modules = ["core-ktx", "appcompat", "material", "constraintlayout", "lifecycle-livedata-ktx", "lifecycle-viewmodel-ktx", "navigation-fragment-ktx", "navigation-ui-ktx"] }

使用上跟方式一完全一样,默认我们不需要在settings.gradle.kts配置任何东西。gradle会自动加载gradle目录下的libs.versions.toml文件,默认的名称也是libs。
当然,如果你想把文件名字或者路径改一下也完全没问题,改完后手动配置下依赖即可。

例如

  versionCatalogs {
        create("libs") {
            from(files("version-catalog/libs.versions.toml"))
        }
    }

发布到远端

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

Version Catalog发布也比较简单,按照 官方文档 来即可。
发布完成后,直接依赖远程的配置就可以了。
示例:

    versionCatalogs {
        create("libs") {
           from("com.xeonyu:version-catalog:0.0.2-SNAPSHOT")
        }
}

到这里,我们就实现了共享版本目录了。

配合Include Build 简化配置

解决完共享依赖的问题后,我们还可以配合之前用的Include Build来简化日常的依赖配置。
比如作为一个module,它的配置比较固定,无非就是些 minSdk,targetSdk,混淆配置,插件配置之类的,而且每个module的配置基本一致,同时作为公司内部的组件,我们希望组件的版本(例如minSdk,targetSdk等)能够跟App的版本保持一致,那么我们就可以结合Include Build加上version catalog来实现了。
还有一些三方依赖比如room,therouter等,他们的配置是固定成套的,我们可以通过写插件的方式把他们的配置集中起来,项目需要用到时直接一行代码就能搞定依赖了。

示例:

plugins {
    alias(libs.plugins.yzq.android.application)
    alias(libs.plugins.yzq.android.room)
}

插件部分不是很通用,一般需要根据自身需要编码定制,这里就不啰嗦了,主要是提供些思路,抛砖引玉。
关于插件的发布可以参考
发布Gradle插件 文档,剩下的就是写插件发布然后应用了。

总结

总而言之,Version Catalog和Include Build可以帮助开发人员更好地管理和配置项目中的依赖库和插件,提高开发效率,并保持版本的统一性。同时,通过发布Version Catalog和编写Gradle插件,可以实现依赖的共享和集中管理。


如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

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

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

相关文章

商业综合体智能管理系统

自主研发的商业综合体智能管理系统和智能硬件,并针对行业不同需求,推出了不同行业的创新解決方案和服务。该系统能够提高商业综合体的管理效率和安全性,为商业综合体的经营和服务增加更多的价值。全自动智能完成无需人工干预,从而…

【企业架构框架】SOGAF架构类型/模式

模式概述 Salesforce 运营、治理和架构框架 (SOGAF) 将新窗口企业架构框架中的 MIT-CISR Salesforce 实施和程序。在此框架内,有四种通用架构类型: 单一系统核心模型模板多系统 每个特定的架构类型对应一个支持 SOGAF 运营模型。架构类型的选择还应包括…

前端搭建名言生成器(内含源码)

目录 前言 名言生成器 页面搭建 功能实现 前言 今天呢我们来给大家展示的,就是一个非常非常简单的名言生成器, 那么它的功能的非常简单,就是我们通过点击按钮,然后可以生成名人名言,然后我们也可以点击按钮将它分享到…

C++图形开发(1):graphics图形库简介与安装

文章目录 1.引入2.安装(1)在官网下载安装包(2)安装 3.检验 1.引入 为了帮助大家实现真正的、更有意思的C开发,本人决定开一个C图形开发的专栏,来制作更多的有意思的游戏、程序。 首先我们要了解的&#x…

MySQL 分库分表实战之ShardingSpare(分库分表+读写分离)

文章目录 概要一、安装二、配置2.1、 通用配置2.2、 分片配置2.3、读写分离 三、演练3.1、读写分离3.2、分库分表3.3、分库分表读写分离 4、总结 概要 市面上MySQL分库分表中间件还是很多的,主要分为两大类:应用层依赖类中间件(比如sharding…

电气自动化入门——总览

目录 学习路线 电气设备组成部分 设备驱动类设备元件 常用电机类型 电机控制器类型​编辑 气缸类设备驱动 设备控制与数据采集监控部分 小型PLC 中大型PLC 数据采集与监控 HMI——人机交互界面 IPC——工控机 设备检测反馈元件——传感器 学习路线 电气设备组成部分 …

第 352 场LeetCode周赛

A 最长奇偶子数组 枚举满足条件的左端点能延续的最长右端点 class Solution { public:int longestAlternatingSubarray(vector<int> &nums, int threshold) {int res 0;int n nums.size();for (int i 0; i < n;) {if (nums[i] % 2 0 && nums[i] <…

Spring Boot 中的 Spring Cloud Hystrix:原理和使用

Spring Boot 中的 Spring Cloud Hystrix&#xff1a;原理和使用 什么是 Spring Cloud Hystrix&#xff1f; Spring Cloud Hystrix 是一个用于处理分布式系统中故障的库。它实现了熔断器模式&#xff0c;可以防止由于故障服务的连锁反应而导致整个系统崩溃。Spring Cloud Hyst…

RabbitMq应用延时消息

一.建立绑定关系 package com.lx.mq.bind;import com.lx.constant.MonitorEventConst; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annota…

innovus: 如何让两个generate clock balance skew group?

如题&#xff0c;在sdc约束中两个generate clock被设置到同一个clock group中&#xff0c;工具虽然会生成对应的两个skew group&#xff0c;但是阅读ccoot_spec发现工具并没有让两个skew group进行balance&#xff0c;这时就需要手动设置balance skew group。 方法如下: 在读…

回归预测 | MATLAB实现WOA-DBN鲸鱼算法优化深度置信网络的多输入回归预测

回归预测 | MATLAB实现WOA-DBN鲸鱼算法优化深度置信网络的多输入回归预测 目录 回归预测 | MATLAB实现WOA-DBN鲸鱼算法优化深度置信网络的多输入回归预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 基于鲸鱼算法优化深度置信网络(WOA-DBN)的数据回归预测&…

微软AI太会了,示爱威胁PUA!

微软在以ChatGPT为基础的最新搜索引擎New Bing在公测仅一周后就引发了人们的担忧和恐惧。用户反馈&#xff0c;New Bing不仅会表现出类似示爱、PUA和威胁人类等人类特有的行为&#xff0c;还可能超越人类意志和价值观&#xff0c;并违反“阿西莫夫的机器人三定律”。这引起了人…

ODERBY的运行原理

定义表: CREATE TABLE t (id int(11) NOT NULL,city varchar(16) NOT NULL,name varchar(16) NOT NULL,age int(11) NOT NULL,addr varchar(128) DEFAULT NULL,PRIMARY KEY (id),KEY city (city) ) ENGINEInnoDB; SQL语句: select city,name,age from t where city杭州 orde…

【第二章 flutter学习之Dart介绍】

文章目录 前言一、Dart环境搭建安装 Dart Sdkvscode安装dart 前言 Dart是谷歌开发的计算机编程语言&#xff0c;诞生于2011&#xff0c;可以被用于web、服务器、移动应用、物联网应用的开发。要学习flutter必须会Dart 一、Dart环境搭建 安装 Dart Sdk 官网&#xff1a;https…

Kubernetes(k8s)容器编排Service

目录 1 Service概述1.1 为什么要有Service1.2 Service实现原理 2 Service 的类型3 Service示例3.1 准备工作3.1.1 创建deployment3.1.2 启动deployment3.1.3 访问测试 3.2 ClusterlP类型3.2.1 编辑资源清单3.2.2 应用Service3.2.3 访问测试3.2.4 删除Pod3.2.5 访问测试 3.3 Nod…

Python学习——类与对象

一、编程的两大思想 &#xff08;1&#xff09;面向过程 事物比较简单&#xff0c;用简单的线性思维即可解决 &#xff08;2&#xff09;面向对象 事物比较复杂&#xff0c;用简单的线性思维无法解决 &#xff08;3&#xff09;两者之间的关系 在面对复杂的问题时&#xff0c;宏…

gcc编译过程详解

以一个简单的C代码为例&#xff0c;详细讲解gcc整个编译过程。 1、预处理 主要处理#开头的东西&#xff0c;例如头文件处理、条件编译处理、将宏定义进行替换&#xff0c;还可以去掉注释、添加行号等。预处理的命令如下&#xff1a; gcc -E hello.c -o hello.i #-E表示预处理…

全志V3S嵌入式驱动开发(解决kernel 5.2.y wifi驱动问题)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 wifi模块&#xff0c;之前测试的时候&#xff0c;开发板上用的是esp 8089&#xff0c;当时内核时4.14.y&#xff0c;测试结果也是通过的。印象不是…

《C++ Primer》--学习10

反向迭代器 反向迭代器就是在容器中从尾元素向首元素反向移动的迭代器&#xff0c;递增一个反向迭代器会移动到前一个元素 反向迭代器需要递减运算符 我们只能从既支持也支持--的迭代器来定义反向迭代器&#xff0c;除了 forward_list 外的标准容器都支持 流迭代器不支持递减…

【分布式存储】聊聊共识和一致性

在分布式存储系统中&#xff0c;对于提高性能、可用性、可拓展性来说都有相关机制可以保证&#xff0c;比如复制、切片等&#xff0c;但是一旦涉及到分布式系统中选主的问题&#xff0c;就比较难&#xff0c;因为网络是不可靠的&#xff0c;并且可能还有拜占庭将军问题。所以如…