Android Gradle依赖经验总结

 

前言:

比较大的APP项目开发中总是会遇到各种Gradle编译依赖问题等,这里根据以往的踩坑经验做个总结,以方便大家日后能够更高效率的处理Gradle相关依赖的问题。

 

一、依赖配置

目前 Gradle 版本支持的依赖配置有:

implementation、api、compileOnly、runtimeOnly annotationProcessor

已经废弃的配置有:compile、provided、apk、providedCompile。

各配置项具体作用如下[括号后面为对应的已废弃的配置]

  • implementation  (compile):会添加依赖到编译路径,并且会将依赖打包到输出(aar或apk),但是在编译时不会将依赖的实现暴露给其他module,也就是只有在运行时其他module才能访问这个依赖中的实现。使用这个配置,可以显著提升构建时间,因为它可以减少重新编译的module的数量。建议,尽量使用这个依赖配置。

  • api  (compile):与 compile功能完全一样,会添加依赖到编译路径,并且会将依赖打包到输出(aar 或a pk)。与 implementation 不同,这个依赖可以传递,其他 module 无论在编译时和运行时都可以访问这个依赖的实现,也就是会泄漏一些不应该不使用的实现。举个例子,A 依赖 B,B 依赖 C,如果都是使用 api 配置的话,A 可以直接使用 C 中的类(编译时和运行时)。而如果是使用 implementation 配置的话,在编译时,A 无法访问 C 中的类。

  • compileOnly  (provided):Gradle 把依赖加到编译路径,编译时使用,不会打包到输出(aar 或 apk)。这可以减少输出的体积,在只在编译时需要,在运行时可选的情况,很有用。

  • runtimeOnly  (apk):只在生成apk的时候参与打包,编译时不会参与,很少用。

  • annotationProcessor  (compile):用于注解处理器的依赖配置。

 

二、依赖类型

依赖类型主要有如下三种:

apply plugin: 'com.android.application'
 
android { ... }
 
dependencies {
    // 【1、本地源码依赖】Dependency on a local library module
    implementation project(":mylibrary")
 
    // 【2、本地libs目录jar包等依赖】Dependency on local binaries
    implementation fileTree(dir: 'libs', include: ['*.jar'])
 
    // 【3、远程Maven仓库等依赖】Dependency on a remote binary
    implementation 'com.example.android:app-magic:12.3'
}

 

三、排除依赖透传

1、dependencies中单个依赖排除:

compile('com.hongri.android:accs-huawei:1.1.2@aar') {
        transitive = true
        exclude group: 'com.taobao.android', module: 'accs_sdk_taobao'
}

2、全局配置排除:

configurations {
    compile.exclude module: 'cglib'
    //全局排除原有的tnet jar包与so包分离的配置,统一使用aar包中的内容
    all*.exclude group: 'com.taobao.android', module: 'tnet-jni'
    all*.exclude group: 'com.taobao.android', module: 'tnet-so'
}

3、禁止依赖传递:

compile('com.hongri.android:foundation:1.0') {
    transitive = false
}
 
configurations.all {
    transitive = false
}

4、还可以在单个依赖项中使用 @jar 标识符忽略传递依赖:

compile 'com.hongri.android:foundation:1.0.0@jar'

 

四、查看依赖树:

在Terminal 终端输入以下命令,即可看到项目的依赖关系解析树:

./gradlew app:dependencies

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

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

 

 

五、强制指定依赖

  • 在dependencies中配置之后呢,一般情况下高的版本会覆盖旧的低的版本:
implementation 'com.android.support:appcompat-v7:27.0.2'
  • 如果我们想一直使用某个固定版本,那么可以使用如下的强制依赖实现:
compile('com.hongri.android:foundation:1.0.0') {
    force = true
}
//或者进行全局配置
configurations.all {
    resolutionStrategy {
        force 'com.hongri.android:foundation:1.0.0'
        //或这种写法
        forcedModules = ['com.hongri.android:foundation:1.0.0']
    }
}

 

六、定义解析策略

1、dependencySubstitution:

dependencySubstitution接收一系列替换规则,允许你通过substitute函数为项目中的依赖替换为你希望的依赖项:

// add dependency substitution rules
dependencySubstitution {
   //将该module所有的远程依赖替换成源码依赖
   substitute module('org.gradle:api') with project(':api')
   //将该module所有源码依赖替换成远程依赖
   substitute project(':util') with module('org.gradle:util:3.0')
}

 

2、eachDependency:

eachDependency允许你在gradle解析配置时为每个依赖项添加一个替换规则,DependencyResolveDetails类型的参数可以让你获取一个requested和使用useVersion()、useTarget()两个函数指定依赖版本和目标依赖。request中存放了依赖项的groupid、module name以及version,你可以通过这些值来筛选你想要替换的依赖项,再通过useVersion或useTarget指定你想要的依赖。

  • 将group是com.android.support且name不等于multidex的所有module版本指定为28.0.2:
configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support') {
            if (!requested.name.startsWith("multidex")) {
                details.useVersion '28.0.2'
            }
        }
    }
}
  • 将所有module为rxjava的依赖,全都指定使用如下版本:‘io.reactivex.rxjava3:rxjava:3.0.0-RC1’:
configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        if (details.requested.name == 'rxjava') {
            //由于useVersion只能指定版本号,不适用于group不同的情况
            details.useTarget group: 'io.reactivex.rxjava3', name: 'rxjava', version: '3.0.0-RC1'
        }
    }
}

 

 

 

参考:

Gradle官网 ResolutionStrategy

配置构建变体

Gradle 的依赖关系处理不当,可能导致你编译异常

 

 

你可能感兴趣的:(gradle,gradle,android,studio)