Android项目Gadle统一依赖管理

news2024/11/26 2:24:50

一.Gradle管理依赖版本

在中大型Android项目中,都会有多个Module进行协同配合。这些module中可能会依赖同一个库的不同版本,这将导致一些问题,要么是代码冲突,要么是APK包体积增大,亦或是项目构建的时间变长,拖慢开发效率。 例如:下图就是在不同的module中依赖同一个库的不同版本。

要解决这个问题我们首先要了解在Android项目中目前有那些方案来引入第三方依赖:

  1. 直接编写(默认方式)
  2. 使用ext扩展抽取公共版本
  3. 使用buildSrc管理依赖
  4. 使用composing builds管理依赖
  5. 使用catalog管理依赖(gradle7版本以上才能用,因此暂时忽略)

二.直接编写(默认方式)

简介

直接编写是Android项目工程自带的默认管理方式,在每一个module中都写死了不同依赖及版本号,因此每次升级依赖库时都需要对每一个module做大量的手动更改。

module_a/build.gradle:

dependencies {
    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    implementation 'com.squareup.okhttp3:okhttp:4.10.0'
}

module_b/build.gradle:

dependencies {
    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    implementation 'com.squareup.okhttp3:okhttp:4.10.0'
}

优点

如果是单个module的项目非常适合这种比较简单的方式,一目了然。远端依赖如果升级了新的版本会有提供升级的功能。

缺点

如果项目中有多个不同的module,你需要在多个module的build.gradle文件中都做对应的配置,还要确保依赖的库的版本号一致,配置项要重复编写多次。

三.使用gradle的extra属性(推荐)

简介

Google在Android官方文档中推荐通过使用gradle的extra属性,将依赖及版本号编写到config.gradle配置文件中,每个module都去依赖config.gradle中的版本,从而达到统一管理的目的。

Root-level config.gradle

ext {
  versions = [
    core_ktx: "1.7.0",
    appcompat: "1.4.1",
    okhttp: "4.10.0"
  ]
  libs = [
    core_ktx :"androidx.core:core-ktx:${versions.core_ktx}",
    appcompat: "androidx.appcompat:appcompat:${versions.appcompat}",
    okhttp: "com.squareup.okhttp3:okhttp:${versions.rxjava}"
  ]
}

Root-level build.gradle

apply from: "config.gradle"

module_a/build.gradle


dependencies {
    implementation libs.core_ktx
    implementation libs.appcompat
    implementation libs.okhttp
}    

module_b/build.gradle

dependencies {
    implementation libs.core_ktx
    implementation libs.appcompat
    implementation libs.okhttp
}   

优点

将版本统一管理起来了,只需要更改config.gradle中的版本号就可以对所有module的依赖版本进行修改。

缺点

  • 不支持代码补全提示。
  • 不支持单击跳转。
  • 多模块开发时,不同模块相同的依赖需要复制粘贴。
  • 依赖版本更新不会提示。

四.使用buildSrc管理(推荐)

简介

Gradle文档中说到:当运行 Gradle 时会检查项目中是否存在一个名为 buildSrc 的目录。 然后Gradle 会自动编译并测试这段代码,并将其放入构建脚本的类路径中, 对于多项目构建,只能有一个 buildSrc 目录,该目录必须位于根项目目录中, buildSrc 是 Gradle 项目根目录下的一个目录, 它可以包含我们的构建逻辑,与脚本插件相比,buildSrc应该是首选,因为它更易于维护、重构和测试代码。

使用步骤

1.项目根目录下新建一个名为buildSrc的文件夹(注意:名字必须是 buildSrc,因为上文提到了运行 Gradle 时会检查项目中是否存在一个名为 buildSrc 的目录),然后在 buildSrc 文件夹里创建名为 build.gradle.kts 的文件。

build.gradle.kts

plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
    google()
    gradlePluginPortal()
}
  1. buildSrc下新建目录src\main\kotlin这里的目录只是建议,输入其他的名称也是可以的。

  2. src\main\kotlin中创建Dependencies.kt等配置文件:
    Dependencies.kt

object BuildVersion {
    const val compileSdk = 30
    const val buildTools = "30.0.2"
    const val minSdk = 21
    const val targetSdk = 30
    const val versionCode = 1
    const val versionName = "1.0.0"
}

object Versions {
    val core_ktx = "1.7.0"
    val appcompat = "1.4.1"
    val okhttp = "4.10.0"
}

object Libs {
    val core_ktx = "androidx.core:core-ktx:${Versions.core_ktx}"
    val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}"
    val okhttp = "com.squareup.okhttp3:okhttp:${Versions.okhttp}"
}

4.经过上面步骤后,执行一次Gradle Sync任务,就可以在Android Studio中访问Dependencies.kt中任何值了。 看起来结果与“ext”方式非常相似,但是它支持自动补全和单击跳转功能。

module_a/build.gradle

android {
    compileSdkVersion BuildVersion.compileSdk
    buildToolsVersion BuildVersion.buildTools

    defaultConfig {
        minSdkVersion BuildVersion.minSdk
        targetSdkVersion BuildVersion.targetSdk
        versionCode BuildVersion.versionCode
        versionName BuildVersion.versionName
        ...
    }

    ...
}

dependencies {
    implementation Libs.core_ktx
    implementation Libs.appcompat
    implementation Libs.okhttp
}

module_b/build.gradle

android {
    compileSdkVersion BuildVersion.compileSdk
    buildToolsVersion BuildVersion.buildTools

    defaultConfig {
        minSdkVersion BuildVersion.minSdk
        targetSdkVersion BuildVersion.targetSdk
        versionCode BuildVersion.versionCode
        versionName BuildVersion.versionName
        ...
    }

    ...
}

dependencies {
    implementation Libs.core_ktx
    implementation Libs.appcompat
    implementation Libs.okhttp
}

优点

  • 将版本统一管理起来了,我们只需要更改Dependencies.kt中的版本号就可以对所有module的依赖版本进行修改。
  • 支持 AndroidStudio 自动补全。
  • 支持依赖库的点击跳转。

缺点

  • buildSrc 依赖更新将重新构建整个项目,buildSrc 依赖更新将重新构建整个项目,项目越大,重新构建的时间就越长,造成不必要的时间浪费。
  • 依赖版本更新不会提示。

五.使用Composing builds管理

简介

摘自 Gradle 文档:复合构建只是包含其他构建的构建. 在许多方面,复合构建类似于 Gradle 多项目构建,不同之处在于,它包括完整的 builds,而不是包含单个 projects

使用步骤

  1. 新建Android library工程module名为version_plugin,包名为com.huke.plugin(非固定名可以自取)并删除多余的文件及文件夹。

  2. 修改version_plugin工程中的 build.gradle文件。

apply plugin: 'kotlin'
apply plugin: 'java-gradle-plugin'

buildscript {
    repositories {
        google()
        maven { url 'https://jitpack.io' }
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
        maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
        gradlePluginPortal()
        mavenCentral()
    }

    dependencies {
        // 因为使用的 Kotlin 需要需要添加 Kotlin 插件,需要和主工程对应,不然就出现两个版本了
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.0"
    }

}

repositories {
    google()
    maven { url 'https://jitpack.io' }
    maven {url 'https://maven.aliyun.com/nexus/content/repositories/releases/'}
    maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
    maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' }
    mavenCentral()
}

dependencies {
    //添加Gradle相关的API,否则无法自定义Plugin和Task
    implementation gradleApi()
    implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.0"
}

compileKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

compileTestKotlin {
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

gradlePlugin {
    plugins {
        version {
            // 在 app 模块需要通过 id 引用这个插件
            id = 'com.huke.plugin'
            // 实现这个插件的类的路径
            implementationClass = 'com.huke.version.VersionPlugin'
        }
    }
}

注意,插件中的build.gradle文件中的 kotlin-gradle-plugin 版本要和主工程对应。

  1. 在项目 settings.gradle 文件内添加includeBuild("version_plugin"),添加完毕以后可以Rebuild项目。
includeBuild('version_plugin')
  1. 在plugin-version module中创建VersionPlugin类,继承Plugin。这里可以空实现,也可以根据需求添加其他代码。
import org.gradle.api.Plugin
import org.gradle.api.Project

class VersionPlugin : Plugin<Project> {
    override fun apply(target: Project) {

    }
}

5.在plugin-version module中创建Deps.kt文件用来管理依赖包和版本号,可以声明多个kt文件。

/**
 * 配置和 build相关的
 */
object BuildVersion {
    const val compileSdk = 30
    const val buildTools = "30.0.2"
    const val minSdk = 21
    const val targetSdk = 30
    const val versionCode = 1
    const val versionName = "1.0.0"
    
}

object Versions {
    val core_ktx = "1.7.0"
    val appcompat = "1.4.1"
    val okhttp = "4.10.0"
}

object Libs {
    val core_ktx = "androidx.core:core-ktx:${Versions.core_ktx}"
    val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}"
    val okhttp = "com.squareup.okhttp3:okhttp:${Versions.okhttp}"
}
  1. 在app或module的 build.gradle 中使用plugin-version中的依赖
    module_a/build.gradle
plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'com.ileo.plugin.version'
    //引用插件框架
    id 'com.huke.plugin'
}
/导入依赖包下的类
import com.huke.version.*
android {
    compileSdk BuildVersion.compileSdk

    defaultConfig {
        applicationId "com.huke.composingbuildsdemo"
        minSdk BuildVersion.minSdk
        targetSdk BuildVersion.targetSdk
        versionCode BuildVersion.versionCode
        versionName BuildVersion.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 Dependencies.core_ktx
    implementation Dependencies.appcompat
    implementation Dependencies.okhttp
}

module_b/build.gradle

plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
    id 'com.ileo.plugin.version'
    //引用插件框架
    id 'com.huke.plugin'
}
/导入依赖包下的类
import com.huke.version.*
android {
    compileSdk BuildVersion.compileSdk
    defaultConfig {
        applicationId "com.huke.composingbuildsdemo"
        minSdk BuildVersion.minSdk
        targetSdk BuildVersion.targetSdk
        versionCode BuildVersion.versionCode
        versionName BuildVersion.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 Dependencies.core_ktx
    implementation Dependencies.appcompat
    implementation Dependencies.okhttp
}

tip 如果import com.huke.version.*无法导入可以先使用implementation添加依赖再进行import导包或者 使用com.huke.version.Dependencies.okhttp进行导入。

优点

  • 支持依赖统一管理。
  • 支持单向跟踪。
  • 代码自动补全。
  • 依赖更新时,不会重新构建整个项目。

缺点

  • 配置较为复杂。
  • 依赖版本更新不会提示。

六.总结

直接编写(默认方式)这种方式适合单一module项目使用,并且它并不是一无是处,在远端的依赖版本更新时,它会有提示功能,这是其他几种方式目前无法做到的。使用gradle的extra属性这种方式是google之前推荐的一种方式,不过它并不支持点击跳转,如果要查看依赖的详情必须要进行搜索查看找到对应的源头进行查看。 使用buildSrc管理这种方式比较简单,支持跳转,但是要注意版本号变更以后编译时间比较长。使用Composing builds管理也支持跳转,但是配置稍复杂。目前看来这几种方案似乎都没有做到完美,大家可以根据自己的工程灵活选择其中一种方式使用。

扩展阅读

统一依赖管理Composing builds
项目依赖统一管理方案
Android项目管理依赖方式总结
Android - 依赖统一管理
再见吧 buildSrc, 拥抱 Composing builds 提升 Android 编译速度
Composing builds
统一依赖管理Composing builds

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

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

相关文章

在Revit里如何将普通墙与曲面墙的内壁连接

在Revit里如何将普通墙与曲面墙的内壁连接&#xff1f;创建异形建筑时&#xff0c;为了达到如图1所示的效果&#xff0c;该如何操作&#xff1b; 我们可以使用体量建模的方式来创建该类建筑&#xff0c;要点在于如将幕墙与曲面墙的内壁连接。具体方法如下&#xff1a; 一、创建…

ASP.NET Core+Element+SQL Server开发校园图书管理系统(一)

随着技术的进步&#xff0c;跨平台开发已经成为了标配&#xff0c;在此大背景下&#xff0c;ASP.NET Core也应运而生。本文主要基于ASP.NET CoreElementSql Server开发一个校园图书管理系统为例&#xff0c;简述基于MVC三层架构开发的常见知识点&#xff0c;仅供学习分享使用&a…

ubuntu20.04下出现protoc与gazebo版本问题

ubuntu20protocgazebo问题描述问题定位解决方案问题描述 今天在搞路径规划算法时&#xff0c;从git上拉下来一个算法&#xff0c;ros环境那些都有&#xff0c;但是在编译的时候出现了如下图所示的一下问题&#xff1a;&#xff08;为了方便搜索关键词&#xff09; In file incl…

锂离子电池热失控预警资料整理(三)

此前 个人搜集了一些锂电池热失控预警相关期刊、文献&#xff0c;并整理了一些个人认为重要的逻辑、知识点&#xff0c;希望通过此分享让有需要的人了解一些内容&#xff0c;如有问题欢迎同我探讨~ 锂离子电池热失控预警资料整理&#xff08;三&#xff09;九、基于数据分析的锂…

C语言基于FOC控制算法和STM32主控芯片的双路直流无刷电机控制器源码

【FOCSTM32】双路直流无刷电机矢量控制器-使用文档 &#x1f4d5; 介绍 控制器主控芯片采用STM32F405RGT6&#xff0c;控制器底层基于HAL库和FreeRTOS实时操作系统&#xff0c;预留CAN、USART、SWD、USB接口各一&#xff0c;便于通信和控制的工程应用。该控制器提供双路无刷电…

2022年艺术品和古董投资策略研究报告

第一章 行业概况 艺术品是艺术家智力劳动成果的结晶。作为一种特殊商品流通于艺术市场&#xff0c;与其他商品相同的是&#xff0c;它也具备普通商品的基本属性&#xff1a;使用价值和价值。不同的是&#xff0c;艺术品的使用价值体现在精神层面而不是物质层面上&#xff0c;它…

RabbitMQ消息队列实战(1)—— RabbitMQ的体系

RabbitMQ是一个开源的消息代理和队列服务器&#xff0c;用来在不同的应用之间共享数据。1983年&#xff0c;被认为是RabbitMQ的雏形的Teknekron创建&#xff0c;首次提出了消息总线的概念。中间经历过数个阶段的发展&#xff0c;一直到2004年&#xff0c;AMQP&#xff08;Advan…

02.指针的进阶

1.字符指针 在指针的类型中我们知道有一种指针类型为字符指针 char* ; 一般使用: int main() {char ch w;char *pc &ch;*pc w;return 0; } char * p---const char * p(因为常量字符串不能被修改) #include<stdio.h> int main() {const char * pstr "hel…

从汇编的角度了解C++原理——虚函数

文章目录1、虚函数1.1、虚函数储存结构1.2、子类重写虚函数1.3、在栈上调用虚函数1.4、在堆上调用虚函数(通过指针调用&#xff0c;多态)本文用到的反汇编工具是objconv&#xff0c;使用方法可以看我另一篇文章https://blog.csdn.net/weixin_45001971/article/details/12866064…

编译基于armV8架构的opencv,并在rock3a开发板上运行

近期在基于arm开发板做图像识别任务开发时&#xff0c;需要用到Opencv库 之前在做rknpu开发时&#xff0c;开发sdk里面已经集成了opencv 但是该opencv开发包不能实现imshow/VideoCapture等函数&#xff0c;经过调研&#xff0c;决定对opencv源代码进行编译&#xff0c;生成arm…

安科瑞能耗监测系统在新疆昌吉市政务中心项目的研究与应用

安科瑞 华楠摘要&#xff1a;大型公共建筑总面积不足城镇建筑总面积的4%&#xff0c;但总能耗却占全国城镇总耗电量的22%&#xff0c;大型公共建筑单位面积年耗电量达到70&#xff5e;300KWh&#xff0c;为普通居民住宅的10&#xff5e;20倍。公共建筑是节能大户和节能核心&…

Delphi 11.2 安装 CnWizards 组件包

官方网址&#xff1a;https://www.cnpack.org/showdetail.php?id900&langzh-cn 开源免费的组件包&#xff0c;大大提高了开发效率&#xff0c;再次感谢大佬们的无私奉献 这个组件包主要是为了实现一些delphi没有的便捷设置&#xff0c;以及能给delphi增加了一些好用的辅助…

惊艳的产品背后,是锐利的设计思维

缘起 几年前&#xff0c;我偶然用一个 叫 Zine 的小app 写了两篇文章&#xff0c;感觉非常好。 后来在网上认识 了Zine 团队的创始人 Louis&#xff0c;也喜欢上了他们的另一个 App&#xff1a;Varlens&#xff0c; 最近他们推出了记笔记的 App Lattics&#xff0c;一些功能也…

《 Unity Shader 入门精要》 第3章 Unity Shader 基础

第3章 Unity Shader 基础 3.1 Unity Shader 概述 材质与 Unity Shader 在 Unity 中我们通常需要将材质&#xff08;Material&#xff09; 和 Unity Shader 配合使用&#xff0c;常见流程如下&#xff1a; 创建一个材质创建一个 Unity Shader&#xff0c; 并将它赋给材质将材…

Android View类

布局定义了应用中的界面结构&#xff08;例如 Activity 的界面结构&#xff09;。布局中的所有元素均使用 View 和 ViewGroup 对象的层次结构进行构建。View 通常用于绘制用户可看到并与之交互的内容。ViewGroup 则是不可见的容器&#xff0c;用于定义 View 和其他 ViewGroup 对…

AppScan自定义扫描策略,扫描针对性漏洞

系列文章 AppScan介绍和安装 AppScan 扫描web应用程序 AppScan被动手动探索扫描 AppScan绕过登录验证码深入扫描 第五节-AppScan自定义扫描策略&#xff0c;扫描针对性漏洞 AppScan安全扫描往往速度是很慢的&#xff0c;有些场景下他的扫描项目又不是我们需要的&#xff0c;…

如何实现六轴机械臂的逆解计算?

1. 机械臂运动学介绍 机械臂运动学 机器人运动学就是根据末端执行器与所选参考坐标系之间的几何关系&#xff0c;确定末端执行器的空间位置和姿态与各关节变量之间的数学关系。包括正运动学&#xff08;Forward Kinematics&#xff09;和逆运动学&#xff08;Inverse Kinemati…

渔业养殖远程监控系统解决方案

传统的水产养殖依靠养殖者的经验进行观察&#xff0c;信息不准确&#xff0c;调控不及时&#xff0c;养殖规模扩大难&#xff0c;人工成本高。除此之外传统水产养殖以个户居多&#xff0c;生产管理方式粗放&#xff0c;个体生产能力不足&#xff0c;养殖产品的品质难以保障。 …

AppScan扫描报告

系列文章 AppScan介绍和安装 AppScan 扫描web应用程序 AppScan被动手动探索扫描 AppScan绕过登录验证码深入扫描 AppScan自定义扫描策略&#xff0c;扫描针对性漏洞 第六节-AppScan扫描报告 1.加载扫描结果 1.点击【打开】 2.选择之前保存过的扫描结果 3.等待加载完成 …

RK35XX(3568) Android WSL ubuntu22.04 编译环境配置

前言&#xff1a;装Ubuntu真机操作是很流畅但是没什么软件&#xff0c;装Vmware虚拟机操作卡顿配置也麻烦。那不如试一试wsl吧&#xff0c;命令行操作&#xff0c;流程又快捷wsl简介&#xff1a;适用于 Linux 的 Windows 子系统可让开发人员按原样运行 GNU/Linux 环境 - 包括大…