Android Gradle 插件Android 依赖管理 ⑥ ( 依赖冲突处理 | transitive 依赖传递设置 | exclude 依赖排除设置 | force 强制指定依赖库 )

Posted 韩曙亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Gradle 插件Android 依赖管理 ⑥ ( 依赖冲突处理 | transitive 依赖传递设置 | exclude 依赖排除设置 | force 强制指定依赖库 )相关的知识,希望对你有一定的参考价值。

文章目录





一、查询 android 依赖库的配置



在遇到 依赖冲突 时 , 如果要 排查某个依赖的子库 时 , 就需要对该依赖库非常熟悉 , 最好是找出该依赖库位置 , 并 分析该依赖库的 Maven 配置文件 , 即 pom.xml 配置文件 ; 下面以 com.android.support:appcompat-v7 依赖库 为例进行演示 , 这个库经常会造成依赖冲突 ;

Android 官方提供的依赖库 , 都放在 SDK 的 extras 目录 下 , 如下图所示 :

其中 Android Support 依赖库的路径位置 , 在 D:\\001_Develop\\001_SDK\\Sdk\\extras\\android\\m2repository\\com\\android\\support 路径中的依赖库如下图所示 :


这里以 appcompat-v7 依赖库为例 , 查看 23.3.0 版本的 com.android.support:appcompat-v7 依赖库 , 其目录为 D:\\001_Develop\\001_SDK\\Sdk\\extras\\android\\m2repository\\com\\android\\support\\appcompat-v7\\23.3.0 , 依赖库内容如下 :


查看其 appcompat-v7-23.3.0.pom 依赖配置文件 , 发现该 pom 文件中有配置 com.android.support:support-v4 依赖 , pom 配置文件是 Maven 的依赖配置 , 其格式是 Xml 形式的 ;

    <dependency>
      <groupId>com.android.support</groupId>
      <artifactId>support-v4</artifactId>
      <version>23.3.0</version>
      <type>aar</type>
      <scope>compile</scope>
    </dependency>





二、通过 ModuleDependency#transitive 依赖传递设置



dependencies 中配置依赖时 , implementation 依赖配置 后 , 可以 在闭包中 使用 transitive 函数 设置依赖是否传递 ,

  • 如果为 transitive 函数设置 true 参数 , 则 包含传递依赖 ;
  • 如果为 transitive 函数设置 false 参数 , 则 排除传递依赖 ;
dependencies 

    implementation ('androidx.appcompat:appcompat:1.4.1') 
        transitive true // 包括传递依赖, 如果设置为 false 则排除传递依赖
    

ModuleDependency#transitive 函数的原型如下 :

    /**
     * 设置是否应解析此依赖项,包括或排除其可传递依赖项。
     * 属于此依赖项的工件本身可能依赖于其他工件。
     * 后者称为传递依赖。
     *
     * @param transitive 是否应解析可传递依赖项。
     * @return this
     */
    ModuleDependency setTransitive(boolean transitive);




三、通过 ModuleDependency#exclude 设置排除子依赖库



针对依赖库冲突 : 依赖库 A 中 , 包含了 B , C 分库 ,

  • 它们的 所有版本都是 1.0 版本 , 这两个分库是无法分开的 ;
  • 应用突然 单独的依赖了 2.0 版本的 B 依赖库 ,

这就 出现了冲突 , 此时就会 引入了两个版本的 B 依赖库 , 导致了冲突 ;


在依赖库中 , 可以将其中的某个依赖库剔除 , 如 androidx.appcompat:appcompat 依赖库中 , 依赖了

  • androidx.annotation:annotation 依赖库
  • androidx.core:core 依赖库
  • ndroidx.cursoradapter:cursoradapter 依赖库
  • androidx.activity:activity 依赖库
+--- androidx.appcompat:appcompat:1.4.1
|    +--- androidx.annotation:annotation:1.3.0
|    +--- androidx.core:core:1.7.0 (*)
|    +--- androidx.cursoradapter:cursoradapter:1.0.0
|    +--- androidx.activity:activity:1.2.4

使用如下配置 , 在闭包中调用 ModuleDependency#exclude 方法 , 可以排除 androidx.activity:activity 依赖库 ;

设置之后 , 导入 androidx.appcompat:appcompat 依赖库 , 就会将 androidx.activity:activity 依赖库排除出去 , 不再加载该依赖库 ;

dependencies 

    implementation ('androidx.appcompat:appcompat:1.4.1') 

        // 排除 androidx.annotation:annotation 依赖
        exclude group: "androidx.activity", module: "activity"
    


特别注意 : 如果在此处排除了 , 如果在其它地方引用了 androidx.appcompat:appcompat 依赖库 , 则该设置无效 ;


ModuleDependency#exclude 方法函数原型如下 :

/**
 * 添加排除规则以排除此依赖项的可传递依赖项。
 * <p>
 * 排除特定的可传递依赖项并不保证它不会出现
 * 在给定配置的依赖性中。
 * 例如,没有任何排除规则的某些其他依赖项,
 * 可能会引入完全相同的传递依赖关系。
 * 确保从整个配置中排除可传递依赖项
 * 请使用每个配置的排除规则:{@link configuration#getExcludeRules()}。
 * 事实上,在大多数情况下,配置每个依赖项排除的实际意图
 * 实际上是从整个配置(或类路径)中排除依赖项。
 * <p>
 * 如果您的意图是排除特定的可传递依赖关系
 * 因为您不喜欢它引入配置的版本
 * 然后考虑使用强制版本的功能:{@link ResolutionStrategy#force(Object…)}。
 *
 * <pre class='autoTested'>
 * plugins 
 *     id 'java' // so that I can declare 'implementation' dependencies
 * 
 *
 * dependencies 
 *   implementation('org.hibernate:hibernate:3.1') 
 *     //excluding a particular transitive dependency:
 *     exclude module: 'cglib' //by artifact name
 *     exclude group: 'org.jmock' //by group
 *     exclude group: 'org.unwanted', module: 'iAmBuggy' //by both name and group
 *   
 * 
 * </pre>
 *
 * @param excludeProperties 定义排除规则的属性。
 * @return this
 */
ModuleDependency exclude(Map<String, String> excludeProperties);

特别注意 : 如果在此处排除了 , 如果在其它地方引用了 androidx.appcompat:appcompat 依赖库 , 则该设置无效 ;





四、通过 configuration 配置排除子依赖库



首先 , 执行

gradlew app:dependencies --configuration releaseRuntimeClasspath

命令 , 查看 androidx.appcompat:appcompat 依赖库中 , 包含 androidx.activity:activity 依赖库 , 如下图所示 ;



然后 ,configurations#configuration 脚本块 中 , 配置如下依赖配置 :

configurations 
    configuration
        all*.exclude group: "androidx.activity", module: "activity"
    


dependencies 

    implementation 'androidx.appcompat:appcompat:1.4.1' 


最后 , 再执行

gradlew app:dependencies --configuration releaseRuntimeClasspath

命令 , 查看 androidx.appcompat:appcompat 依赖库中 , 不再包含 androidx.activity:activity 依赖库 ;





五、force 强制指定依赖库



configurations.all#resolutionStrategy 脚本块 中 , 可以 使用 force 强制指定依赖库 ;

使用如下代码 , 将 androidx.appcompat:appcompat 依赖库 , 强制指定为 1.2.0 版本 , 即使有更高版本的 androidx.appcompat:appcompat:1.4. 依赖库 , 也会强制使用该 androidx.appcompat:appcompat:1.2.0 低版本依赖库 ;

configurations.all 
    resolutionStrategy 
        force 'androidx.appcompat:appcompat:1.2.0'
    


dependencies 
    implementation 'androidx.appcompat:appcompat:1.4.1'


执行

gradlew app:dependencies --configuration releaseRuntimeClasspath

命令 , 查看 androidx.appcompat:appcompat 依赖库中 , 发现有 1.4.1 高版本依赖库 , 但是还是被强制使用了 1.2.0 版本的依赖库 ;

以上是关于Android Gradle 插件Android 依赖管理 ⑥ ( 依赖冲突处理 | transitive 依赖传递设置 | exclude 依赖排除设置 | force 强制指定依赖库 )的主要内容,如果未能解决你的问题,请参考以下文章

Android Gradle 插件Gradle 依赖管理 ① ( org.gradle.api.Project 配置 | Android Gradle 插件配置与 Gradle 配置关联 ) ★

Android Gradle 插件Gradle 自定义 Plugin 插件 ⑥ ( 在 buildSrc 模块中依赖 Android Gradle 插件 | 完整代码示例 )

Android Gradle 插件Gradle 自定义 Plugin 插件 ⑥ ( 在 buildSrc 模块中依赖 Android Gradle 插件 | 完整代码示例 )

Android Gradle 插件Android Module 模块 build.gradle 构建脚本 Groovy 语法分析 ① ( Gradle 二进制插件引入 | Gradle依赖配置 )

Android Gradle 插件Android Module 模块 build.gradle 构建脚本 Groovy 语法分析 ① ( Gradle 二进制插件引入 | Gradle依赖配置 )

Android Gradle 插件Gradle 依赖管理 ④ ( Android Gradle 插件中注册的依赖分组 | implementation | api | compileOnly )