查看模块依赖项,自定义构建逻辑

查看模块依赖项

一些直接依赖项可能具有自己的依赖项。此类依赖项称为“传递依赖项”。Gradle 将会自动为您收集并添加这些传递依赖项,无需您手动逐一加以声明。Android Plugin for Gradle 提供了一项任务,用来列出 Gradle 为给定模块解析的依赖项。

对于每个模块,报告还会根据构建变体、测试源代码集和类路径对依赖项进行分组。下面是一个应用模块的依赖项示例报告,其中按该模块的调试构建变体的运行时类路径和该模块的插桩测试源代码集的编译类路径对依赖项进行了分组。

debugRuntimeClasspath - Dependencies for runtime/packaging
+--- :mylibrary (variant: debug)
+--- com.google.android.material:material:1.0.0@aar
+--- androidx.appcompat:appcompat:1.0.2@aar
+--- androidx.constraintlayout:constraintlayout:1.1.3@aar
+--- androidx.fragment:fragment:1.0.0@aar
+--- androidx.vectordrawable:vectordrawable-animated:1.0.0@aar
+--- androidx.recyclerview:recyclerview:1.0.0@aar
+--- androidx.legacy:legacy-support-core-ui:1.0.0@aar
debugAndroidTest
debugAndroidTestCompileClasspath - Dependencies for compilation
+--- androidx.test.ext:junit:1.1.0@aar
+--- androidx.test.espresso:espresso-core:3.1.1@aar
+--- androidx.test:runner:1.1.1@aar
+--- junit:junit:4.12@jar

如需运行该任务,请按以下步骤操作:
依次选择 View > Tool Windows > Gradle(或点击工具窗口栏中的 Gradle 图标 )。
依次展开 AppName > Tasks > android,然后双击 androidDependencies。Gradle 执行该任务后,系统应该会打开 Run 窗口以显示输出。
如需详细了解如何管理 Gradle 中的依赖项,请参阅 Gradle 用户指南中的依赖项管理基础知识。

修复依赖项解析错误

当您向应用项目添加多个依赖项时,这些直接和传递依赖项可能会相互冲突。Android Gradle 插件会尝试妥善解决这些冲突,但有些冲突可能会导致编译时或运行时错误。

为帮助您调查是哪些依赖项导致了错误,请检查您的应用的依赖项树,从中查找多次出现的依赖项或版本冲突的依赖项。

如果无法轻松识别重复的依赖项,请尝试使用 Android Studio 的界面搜索包含重复类的依赖项,具体操作步骤如下:

  1. 从菜单栏中依次选择 Navigate > Class
  2. 在弹出式搜索对话框中,确保已勾选 Include non-project items 旁边的框。
  3. 输入出现在构建错误中的类的名称。
  4. 检查结果以查找包含该类的依赖项。

下面几部分介绍您可能会遇到的不同类型的依赖项解析错误及其修复方法。

修复重复类错误

如果某个类多次出现在运行时类路径上,您会收到一条与以下内容类似的错误:

Program type already present com.example.MyClass

二进制文件依赖项包含一个库,该库也作为直接依赖项包含在您的应用中。例如,您的应用声明直接依赖于库 A 和库 B,但库 A 已在其二进制文件中包含库 B。
如需解决此问题,请取消将库 B 作为直接依赖项。
您的应用的本地二进制文件依赖项和远程二进制文件依赖项是同一个库。
如需解决此问题,请移除其中一个二进制文件依赖项。

解决类路径之间的冲突

当 Gradle 解析编译类路径时,会先解析运行时类路径,然后使用所得结果确定应添加到编译类路径的依赖项版本。换句话说,运行时类路径决定了下游类路径上完全相同的依赖项所需的版本号。

应用的运行时类路径还决定了 Gradle 需要对应用的测试 APK 的运行时类路径中的匹配依赖项使用的版本号。图 1 说明了类路径的层次结构。


image.png

例如,当应用使用 implementation 依赖项配置加入某个依赖项的一个版本,而库模块使用 runtimeOnly 配置加入该依赖项的另一个版本时,就可能会发生多个类路径中出现同一依赖项的不同版本的冲突。

在解析对运行时和编译时类路径的依赖关系时,Android Gradle 插件 3.3.0 及更高版本会尝试自动解决某些下游版本冲突。例如,如果运行时类路径包含库 A 版本 2.0,而编译类路径包含库 A 版本 1.0,则插件会自动将对编译类路径的依赖关系更新为库 A 版本 2.0,以避免错误。

不过,如果运行时类路径包含库 A 版本 1.0,而编译类路径包含库 A 版本 2.0,插件不会将对编译类路径的依赖关系降级为库 A 版本 1.0,您仍会收到一条与以下内容类似的错误:

Conflict with dependency 'com.example.library:some-lib:2.0' in project 'my-library'.
Resolved versions for runtime classpath (1.0) and compile classpath (2.0) differ.
翻译后:
与项目“ my-library”中的依赖项“ com.example.library:some-lib:2.0”冲突。 解决运行时类路径(1.0)和编译类路径(2.0)的版本不同

如需解决此问题,请执行以下某项操作:

  • 将所需版本的依赖项作为 api 依赖项添加到库模块。也就是说,只有库模块声明相应依赖项,但应用模块也能以传递方式访问其 API。
  • 或者,您也可以同时在两个模块中声明相应依赖项,但应确保每个模块使用的版本相同。不妨考虑配置项目全局属性,以确保每个依赖项的版本在整个项目中保持一致。

应用自定义构建逻辑

本部分介绍的高级主题在您要扩展 Android Gradle 插件或编写自己的插件时很有用。

向自定义逻辑发布变体依赖项

库可以包含其他项目或子项目可能要使用的功能。发布库是向其消费者提供库的过程。库可以控制其消费者在编译时和运行时可访问的依赖项。

有两种不同的配置,它们包含每个类路径的传递依赖项,消费者为了使用相应库而必须使用这些依赖项,具体说明如下:

variant_nameApiElements:此配置包含编译时消费者可使用的传递依赖项。
variant_nameRuntimeElements:此配置包含运行时消费者可使用的传递依赖项。

如需详细了解不同配置之间的关系,请参阅 Java 库插件配置

自定义依赖项解析策略

一个项目可能会依赖于同一个库的两个不同版本,这样会导致依赖项冲突。例如,如果您的项目依赖于模块 A 的版本 1 和模块 B 的版本 2,而模块 A 以传递方式依赖于模块 B 的版本 3,则会出现依赖项版本冲突。

为了解决此冲突,Android Gradle 插件使用以下依赖项解析策略:当插件检测到依赖项关系图中存在同一模块的不同版本时,默认情况下,它会选择版本号最高的一个。

不过,此策略可能并不总是如您所愿。如需自定义依赖项解析策略,请使用以下配置解析任务所需的特定变体依赖项:

variant_nameCompileClasspath:此配置包含适用于给定变体编译类路径的解析策略。
variant_nameRuntimeClasspath:此配置包含适用于给定变体运行时类路径的解析策略。
Android Gradle 插件包含可用于访问每个变体的配置对象的 getter。因此,您可以使用变体 API 查询依赖项解析,如以下示例所示:

resolutionStrategy :解析策略
android {
    applicationVariants.all { variant ->
        // Return compile configuration objects of a variant.
翻译后:返回变体的编译配置对象
        variant.getCompileConfiguration().resolutionStrategy {
        // Use Gradle's ResolutionStrategy API
        // to customize how this variant resolves dependencies.
翻译后:使用Gradle的策略 API 来自定义此变体如何解决依赖关系
            ...
        }
        // Return runtime configuration objects of a variant.
翻译后:返回变体的运行时配置对象
        variant.getRuntimeConfiguration().resolutionStrategy {
            ...
        }
        // Return annotation processor configuration of a variant.
翻译后:返回变体的注释处理器配置
        variant.getAnnotationProcessorConfiguration().resolutionStrategy {
            ...
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容