JakeWharton评价个人代码像是在打地鼠?

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

RxJava3版本迁移的血泪史

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

迁移过程当中遇到了一个小问题,那就是RxAndroid由于没有及时升级,所以内部仍是依赖2.x版本的RxJava,这就致使项目的依赖发生了冲突。android

笔者的解决方式很是简单,既然RxAndroid依赖了不合适的RxJava版本,我就把它的依赖排除掉就能够了:git

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

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

评论发出去了一段时间,并无收到各路大神的批评,笔者便觉得这就是 正确的升级方式,因而在 RxAndroid 的这个 issue沾沾自喜 地进行了分享:api

没想到 JakeWharton 居然看到了个人回复,而且很是直接针对我提供的代码进行了点评:app

翻译过来的意思就是:post

长远来看,制定一个 替换规则 远比经过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

若是您以为文章还差了那么点东西,也请经过关注督促我写出更好的文章——万一哪天我进步了呢?

相关文章
相关标签/搜索