文章 | Ashesh Bharadwaj

翻译 | 承香墨影

授权 承香墨影 翻译、编辑并发布

在 Android Studio 中,Gradle 构建过程对于开发者来说,很大程度上是抽象的。作为一个新的 Android 开发者,我们第一次遇到 Gradle 通常是在 build.gradle 文件中添加一个远程依赖项。

让我们看看如何阅读 Gradle 依赖关系树,并解决与依赖关系有关的问题。

这是我工作中管理的一个项目,我想将 targetVersion 升级到 27,我也在 Gradle 中,更新了新版的 appcompat-v7 支持库到最新的依赖版本 27.0.2。在更改之后,同步项目,在 build.gradle 中出现以下错误提示:

该错误表示我必须使用完全相同版本的支持库。可是我只在我的 build.gradle 中,使用了这个支持库。

Android Studio 的这个提示到底是什么意思?

这个错误提示中,提及到的 com.android.support:animated-vector-drawable:27.0.2com.android.support-v4:21.0.3 是在哪里又被引用了?

如果只是应用程序的直接依赖库,只需要在 build.gradle 中指明依赖就好了,这样非常的清晰明了。但是实际情况并非如此,这些依赖关系可能会进一步拥有自己的依赖关系,这被称为 依赖传递 。Gradle 需要在应用中包含所有的直接或者间接的依赖。

前面 Android Studio 提示的错误信息,正是我们现在讨论的这些传递性依赖关系导致的。

Gradle 必须解决所有的这些依赖关系。包含使用了哪些库?如果两个不同的库对同一个库有不同版本的依赖关系,会发生什么问题?

要查看 Gradle 依赖关系树(Gradle 解析依赖关系的方式),我们可以到位于 Android Studio 底部的 Terminal 选项卡并输入以下命令:

gradlew app:dependencies

这将显示所有 构建变体 的依赖关系解析树。我们可以在上面的命令中添加一个标识来查看特定构建变体的配置。例如 --configuration releaseCompileClasspath 将向我们展示 release 变体的依赖树。

关于构建变体,建议阅读官方文档:

https://developer.android.com/studio/build/build-variants.html

以上是上述命令的输出:

releaseCompileClasspath - Resolved configuration for compilation for variant: release
+--- com.android.databinding:library:1.3.1
| +--- com.android.support:support-v4:21.0.3
| | \--- com.android.support:support-annotations:21.0.3 -> 27.0.2
| \--- com.android.databinding:baseLibrary:2.3.0-dev -> 3.0.1
+--- com.android.databinding:baseLibrary:3.0.1
+--- com.android.databinding:adapters:1.3.1
| +--- com.android.databinding:library:1.3 -> 1.3.1 (*)
| \--- com.android.databinding:baseLibrary:2.3.0-dev -> 3.0.1
+--- com.android.support.constraint:constraint-layout:1.0.2
| \--- com.android.support.constraint:constraint-layout-solver:1.0.2
\--- com.android.support:appcompat-v7:27.0.2
+--- com.android.support:support-annotations:27.0.2
+--- com.android.support:support-core-utils:27.0.2
| +--- com.android.support:support-annotations:27.0.2
| \--- com.android.support:support-compat:27.0.2
| +--- com.android.support:support-annotations:27.0.2
| \--- android.arch.lifecycle:runtime:1.0.3
| +--- android.arch.lifecycle:common:1.0.3
| \--- android.arch.core:common:1.0.0
+--- com.android.support:support-fragment:27.0.2
| +--- com.android.support:support-compat:27.0.2 (*)
| +--- com.android.support:support-core-ui:27.0.2
| | +--- com.android.support:support-annotations:27.0.2
| | \--- com.android.support:support-compat:27.0.2 (*)
| +--- com.android.support:support-core-utils:27.0.2 (*)
| \--- com.android.support:support-annotations:27.0.2
+--- com.android.support:support-vector-drawable:27.0.2
| +--- com.android.support:support-annotations:27.0.2
| \--- com.android.support:support-compat:27.0.2 (*)
\--- com.android.support:animated-vector-drawable:27.0.2
+--- com.android.support:support-vector-drawable:27.0.2 (*)
\--- com.android.support:support-core-ui:27.0.2 (*)

在查找目的之前,理解 Gradle 依赖关系树的格式很重要。

先来谈谈以下三个符号,它们的目的仅用于格式化:

  • +- - - 是依赖分支库的开始。
  • | 标识还是在之前的依赖库中的依赖,显示它依赖的库。
  • \- - - 是依赖库的末尾。

星号(*) 在依赖库的末尾,意味着该库的进一步依赖关系不会显示,因为它们已经列在其他某个子依赖树中。

最重要的标识是 ->

如果 Gradle 发现多个依赖库都依赖到同一个库但是不同版本,那么它必须做出选择。毕竟包含同一个库的不同版本是没有意义的。在这种情况下,Gradle 默认选择该库的最新版本。

例如:

| + — — com.android.support:support-v4:21.0.3
| | \ — — com.android.support:support-annotations:21.0.3 -> 27.0.2

在上面,Gradle 告诉说,在 support-v4:21.0.3 依赖关系树中, support-annotations:21.0.3 依赖于更新的版本 support-annotations:27.0.2 ,所以 27.0.2 将被使用。

现在我们知道如何阅读 Gradle 依赖关系解析树,我们回到本文的核心问题:所有 com.android.support 库必须使用完全相同的版本

所有支持库都属于以下组 com.android.support。正如我们在 Gradle 的依赖关系树中看到的那样,com.android.support:support-v4:21.0.3 是唯一具有版本 21.0.3 并且未解析到最新版本的支持库 27.0.2,这就是造成冲突的原因。

如何解决这个问题?有几种方式,可以做到这一点:

**1、通过 ResolutionStrategy **

通过 ResolutionStrategy 强制指定 Gradle 的版本。

android {
configurations.all {
// To resolve the conflict for com.android.databinding:library:1.3.1
// dependency on support-v4:21.0.3
resolutionStrategy.force 'com.android.support:support-v4:27.0.2'
}
}

关于 ResolutionStrategy 的具体细节,官方文档中有详细描述:

https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.ResolutionStrategy.html

2、在 build.gradle 中指明版本

要在 build.gradle 中,明确指定添加的是 com.android.support:support-v4:27.0.2。这将让Gradle 覆盖旧版本。

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
// To resolve the conflict for com.android.databinding:library:1.3.1
// dependency on support-v4:21.0.3
implementation 'com.android.support:support-v4:27.0.2'
implementation 'com.android.support:appcompat-v7:27.0.2'
}

对我来说,在 build.gradle 中显式添加依赖关系似乎更加的自然,并且可以留下注释。当我们再次更新库来检查它是否仍然需要显式添加时,这个注释将提醒我关注它。

一旦添加并进行项目同步之后,错误文本将消失。现在,如果我们再次运行依赖关系命令,我们将看到support-v4:21.0.3解决-> 27.0.2

大部分时候 Gradle 会正确解决依赖关系。而了解了 Gradle 的依赖关系,我想遇到这样的问题我们应该更清楚如何去解决它。

我希望这篇文章能让我们更进一步了解 Gradle 依赖关系树和解决方案。

今天在公众号后台回复成长『成长』,将会得到我整理的一些学习资料,也能回复『加群』,一起学习进步。

原文链接:

https://proandroiddev.com/android-gradle-and-the-curious-case-of-invisible-dependency-7f1bcc8bb79e

推荐阅读:

【译】Gradle 的依赖关系处理不当,可能导致你编译异常的更多相关文章

  1. gradle查看依赖关系并写入到文本文件的命令

    gradle dependencies>xx.txt

  2. Gradle用户指南(章8:依赖关系管理基础)

    章8:依赖关系管理基础 本章将介绍一些gradle依赖关系管理的基础 什么是依赖关系管理? 简略的说,依赖管理是由两部分组成的.首先,gradle需要知道你要构建或者运行的项目,以便找到它们.我们将这 ...

  3. 解决安装rpm包依赖关系的烦恼 - yum工具介绍及本地源配置方法

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  4. Android Gradle Plugin指南(三)——依赖关系、android库和多项目配置

    原文地址:http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Dependencies-Android-Librari ...

  5. Android注解使用之Dagger2实现项目依赖关系解耦

    前言: 最近牵头发起公司app的重构工作,如何通过重构让项目的耦合降低.开发效率提高,一直是我努力的方向,今天来学习一下一个注解框架Dagger2,然后看看如何使用它来降低项目的耦合. Dagger2 ...

  6. Makefile中头文件在依赖关系中作用

    摘于:http://bbs.csdn.net/topics/120024677 (1)在makefile的依赖关系中用不用体现.h头文件?(2)如果在依赖关系中要体现.h头文件,应该体现到什么层次?= ...

  7. 谈谈.net模块依赖关系及程序结构

    技术为解决问题而生. 上面这个命题并非本文重点,我将来有空再谈这个.本文也并非什么了不起的技术创新,只是分享一下我对.net模块依赖关系及程序结构方面的一些看法.先看一个最最简单的hello worl ...

  8. 类图和对象图教程-类(Class)、接口(Interface)、协作(collaboration)、依赖关系(Dependency)、泛化关系(Generalization)、关联关系(Association)以及实现关系(Realization)

    类图的概念 (转) 一.概述 类图(Class Diagram)是描述类.接口.协作以及它们之间关系的图,用来显示系统中各个类的静态结构.类图是定义其他图的基础,在类图基础上,可以使用状态图.协作图. ...

  9. Ubuntu上安装gtk2.0不能安装的问题,“下列的软件包有不能满足的依赖关系”

    zez@localhoss:~$ sudo apt-get install libgtk2.0-dev正在读取软件包列表... 完成正在分析软件包的依赖关系树       正在读取状态信息... 完成 ...

随机推荐

  1. Splay入门解析【保证让你看不懂(滑稽)】

    BST真是神奇的东西... 而且种类好多呀... 我这个蒟蒻只学会了splay orzCJ老爷,各种树都会 好好好,不说了,直接说splay. 不知道splay是啥,,你也要知道平衡树是啥... 平衡 ...

  2. AC自动机模板3【洛谷3796】

    AC自动机的第三个模板 其实,个人觉得,目前我写的这三个不同的模板完全是可以合并在一起求解的. 只是,在这两个无关联的OJ上,同一个AC自动机都可以完成的问题被拆成了三道题而已. 因此,代码只需要略加 ...

  3. [Luogu2057]善意的投票

    题目戳我 题目描述 幼儿园里有n个小朋友打算通过投票来决定睡不睡午觉.对他们来说,这个问题并不是很重要,于是他们决定发扬谦让精神.虽然每个人都有自己的主见,但是为了照顾一下自己朋友的想法,他们也可以投 ...

  4. Vue-自定义事件之—— 子组件修改父组件的值

    如何利用自定义的事件,在子组件中修改父组件里边的值? 关键点记住:三个事件名字 步骤如下: 这里,相对本案例,父组件定义为Second-module,对应的子组件是Three-module 第一步:你 ...

  5. Spring入门看这一篇就够了

    前言 前面已经学习了Struts2和Hibernate框架了.接下来学习的是Spring框架...本博文主要是引入Spring框架... Spring介绍 Spring诞生: 创建Spring的目的就 ...

  6. java web(转)

    装载:http://www.oschina.net/question/12_52027 OSCHINA 软件库有一个分类——Web框架,该分类中包含多种编程语言的将近500个项目. Web框架是开发者 ...

  7. Cassandra配置多节点集群以及使用雅虎YCSB压测Cassandra 3.11

    这几天在搭Cassandra集群以及对Cassandra的性能测试,步骤还挺多,记录一下. 关于Caaandra在服务器上配置多节点集群,可以参考一下文章: http://blog.csdn.net/ ...

  8. WebService就是这么简单

    WebService介绍 首先我们来谈一下为什么需要学习webService这样的一个技术吧.... 问题一 如果我们的网站需要提供一个天气预报这样一个需求的话,那我们该怎么做????? 天气预报这么 ...

  9. 特定场景下Ajax技术的使用

    ajax介绍 jax技术包含了几种技术:javascript.xml.css.xstl.dom.xhtml和XMLHttpRequest七种技术,所以ajax就像是粘合剂把七种技术整合到一起,从而发挥 ...

  10. 怎么解决VMware“该虚拟机似乎正在使用中”问题

    问题如下: