JakeWharton评价我的代码像是在打地鼠?

2023-10-12 00:59

本文主要是介绍JakeWharton评价我的代码像是在打地鼠?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【标题党警告】本文主要内容为 Gradle依赖替换规则详解

RxJava3版本迁移的血泪史

不久前RxJava正式发布了3.x版本,作为RxJava的爱好者,笔者第一时间对个人项目进行了3.x版本的迁移。

迁移过程中遇到了一个小问题,那就是RxAndroid因为没有及时升级,因此内部还是依赖2.x版本的RxJava,这就导致项目的依赖发生了冲突。

笔者的解决方式非常简单,既然RxAndroid依赖了不合适的RxJava版本,我就把它的依赖排除掉就可以了:

implementation ('io.reactivex.rxjava2:rxandroid:2.1.0')  {exclude group: 'io.reactivex.rxjava2', module: 'rxjava'
}

这样做之后,项目成功将RxJava迁移到了3.x版本,笔者还第一时间在 这篇文章 中进行了如下的评论:

评论发出去了一段时间,并没有收到各路大神的批评,笔者便以为这就是 正确的升级方式,于是在 RxAndroid 的这个 issue 中 沾沾自喜 地进行了分享:

没想到 JakeWharton 竟然看到了我的回复,并且非常直接针对我提供的代码进行了点评:

翻译过来的意思就是:

长远来看,制定一个 替换规则 远比通过exclude这种类似 打地鼠 的方式要好得多。

收到男神的回复令我受宠若惊,但我更迫切需要了解我的代码问题出在了哪里—— 我一直认为我的代码就是正确的处理方案,但事实却证明了我的无知

我翻阅了对应的Gradle文档,Gradle中提供了对应的 依赖替换规则,而我之前一直没有了解过它,这也正是本文的主要内容。

依赖替换规则

依赖替换规则的适用场景分为以下几种:

  • 1.根据某些条件对依赖进行替换;
  • 2.将本地依赖替换为外部依赖;
  • 3.将外部依赖替换为本地依赖;

我们先解释一下 外部依赖本地依赖 是什么。

外部依赖

外部依赖,顾名思义,就是从远程仓库拉取的依赖,也被称为常用的 三方库

// 从远程仓库拉取的开源代码库
implementation 'com.facebook.stetho:stetho:1.5.1'
implementation 'io.reactivex.rxjava3:rxjava:3.0.0-RC0'

本地依赖

本地依赖,也就是我们项目中常见的module,按照**《阿里Java开发手册》**中来描述,也叫做 一方库

implementation project(':library')

好的,现在我们了解了这两个基本概念,问题来了:

知道这些有什么用?

有同学肯定会有这个困惑,这些概念我虽然都了解了,但实际开发过程中我并没有用到这些, 项目依然稳定的迭代和运行,那学习这些东西有什么用呢?

这些规则真的很有用,在实际开发过程中,我们肯定会遇到一些问题,这些问题我们通过baidu或者google的方式绕了过去,但是这真的解决了吗?

比如说 依赖冲突

1.根据某些条件对依赖进行替换

举个例子,很多UI三方库都会依赖RecyclerView,但这么多的依赖库,我们不可避免遇到版本不同导致依赖冲突的情况,一般情况下,我们是这么解决的:

// 将RecyclerView的依赖从这个三方库中排除掉
implementation "xxx.xxx:xxx:1.0.0",{exclude group: 'com.android.support', module: 'recyclerview-v7'
}

RecyclerView的依赖从这个三方库中排除掉,令其使用项目本身的RecyclerView版本,这样项目就可以正常运行了,看起来并没有什么问题。

JakeWharton 非常敏锐地点出了问题的所在——试想,如果项目的依赖比较复杂,也许我们要面对的将是这样的依赖配置:

implementation "libraryA:xxx:1.0.0",{exclude group: 'com.android.support', module: 'recyclerview-v7'
}
implementation "libraryB:xxx:2.2.0",{exclude group: 'com.android.support', module: 'recyclerview-v7'
}
implementation "libraryC:xxx:0.0.8",{exclude group: 'com.android.support', module: 'recyclerview-v7'
}

我们需要将每个依赖了RecyclerView的三方库都通过exclude的方式移除掉本身对应的依赖,这种缝缝补补式地乱堵,不正是在 打地鼠 么。

针对类似这种情况,我们可以在gradle的构建过程中强制指定依赖的版本,以笔者的项目为例,我们针对RxJava的版本依赖进行了统一:

现在,项目中所有RxJava相关的依赖,在构建过程中版本都统一使用了3.0.0-RC0,这样就 避免了依赖冲突,开发者再也不需要针对每一个有RxJava依赖的三方库进行额外的exclude了。

2.本地依赖替换为外部依赖

本地依赖替换为外部依赖,最经典的场景就是SDK的发布测试,如果您有过开源项目的经历,对此一定不会陌生。

以笔者开源的 RxImagePicker 为例,日常开发过程中,sample代码依赖本地的module;新版本发布后,笔者的UI测试代码便需要通过依赖jcenter远程仓库的最新代码。

这种情况下,通过dependencySubstitution便可以非常方便对这两种场景进行切换:

useRemote只是定义在build.gradle文件中的一个变量,作为切换开发-测试环境的开关:

final boolean useRemote = true  

useRemote值为true时,sample依赖远程仓库,当值为false时,sample依赖本地module

看起来代码量反而增加了,实际上,随着项目复杂度的提升,这种全局的配置优点显而易见。

3.将外部依赖替换为本地依赖

该规则和2非常相似,只不过将依赖替换的双方调换了而已,下面是官方的示例代码:

configurations.all {resolutionStrategy.dependencySubstitution {substitute module("org.utils:api") because "we work with the unreleased development version" with project(":api")substitute module("org.utils:util:2.5") with project(":util")}
}

最终的迁移方案?

故事的最后,笔者的解决方案如下:

  • 1.因为group不同,所以需要先将2.xrxjava全局exclude掉;
  • 2.将所有3.xrxjava的依赖版本都统一(文中是3.0.0-RC0);

笔者并不知道这种方式是否就是 JakeWharton 描述的解决方案,但相比较之前而言效果确实更好,如果有更好的依赖管理方案,诚挚希望您能在评论区中进行分享。

感受

GitHub确实是一个神奇的东西,它让我避免固步自封,毕竟世界上最顶尖的开发者们都聚焦于此,在他们眼里,你的代码永远都有着非常广阔的进步空间。

发现自己的短板不是坏事,它可以督促我不断去尝试自我超越,就像我常年放在文章末尾的那句话一样,万一哪天我进步了呢?

关于我

Hello,我是却把清梅嗅,如果您觉得文章对您有价值,欢迎 ❤️,也欢迎关注我的个人博客或者Github。

如果您觉得文章还差了那么点东西,也请通过关注督促我写出更好的文章——万一哪天我进步了呢?

  • 我的Android学习体系
  • 关于文章纠错
  • 关于知识付费

这篇关于JakeWharton评价我的代码像是在打地鼠?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/192099

相关文章

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

使用Spring Cache本地缓存示例代码

《使用SpringCache本地缓存示例代码》缓存是提高应用程序性能的重要手段,通过将频繁访问的数据存储在内存中,可以减少数据库访问次数,从而加速数据读取,:本文主要介绍使用SpringCac... 目录一、Spring Cache简介核心特点:二、基础配置1. 添加依赖2. 启用缓存3. 缓存配置方案方案

MySQL的配置文件详解及实例代码

《MySQL的配置文件详解及实例代码》MySQL的配置文件是服务器运行的重要组成部分,用于设置服务器操作的各种参数,下面:本文主要介绍MySQL配置文件的相关资料,文中通过代码介绍的非常详细,需要... 目录前言一、配置文件结构1.[mysqld]2.[client]3.[mysql]4.[mysqldum

Python多线程实现大文件快速下载的代码实现

《Python多线程实现大文件快速下载的代码实现》在互联网时代,文件下载是日常操作之一,尤其是大文件,然而,网络条件不稳定或带宽有限时,下载速度会变得很慢,本文将介绍如何使用Python实现多线程下载... 目录引言一、多线程下载原理二、python实现多线程下载代码说明:三、实战案例四、注意事项五、总结引

IDEA与MyEclipse代码量统计方式

《IDEA与MyEclipse代码量统计方式》文章介绍在项目中不安装第三方工具统计代码行数的方法,分别说明MyEclipse通过正则搜索(排除空行和注释)及IDEA使用Statistic插件或调整搜索... 目录项目场景MyEclipse代码量统计IDEA代码量统计总结项目场景在项目中,有时候我们需要统计