Gradle依赖管理

依赖分析

项目依赖树样例

  • gradle :moduleName:dependencies查看模块依赖树
  • oldVersion->newVersion 指声明依赖为 OldVersion,但项目中有其它位置声明 newVersion,最终引用 newVersion

依赖树:

releaseRuntimeClasspath - Resolved configuration for runtime for variant: release  
+--- xsl.common:diagnosis-network:1.+ -> 1.0.0
+--- xsl.common:statistics:2.0.4
|    +--- com.sensorsdata.analytics.android:SensorsAnalyticsSDK:1.+ -> 1.9.3
|    |    +--- com.android.support:appcompat-v7:23.1.1 -> 26.1.0 (*)
|    |    \--- org.aspectj:aspectjrt:1.8.10
|    \--- xsl.common:base:2.0.1-SNAPSHOT -> 2.1.6
|         \--- com.meituan.android.walle:library:1.1.5
|              +--- com.android.support:support-annotations:24.1.1 -> 24.2.1
|              \--- com.meituan.android.walle:payload_reader:1.1.5
+--- xsl.common:xslpush:3.0.16
|    +--- xsl.common:base:2.0.3 -> 2.1.6 (*)
|    +--- xsl.common:usercenter:2.2.7 -> 3.4.0
|    |    +--- com.android.support:appcompat-v7:26.1.0 (*)
|    |    \--- com.google.code.gson:gson:2.6.1
|    \--- com.android.support:support-v4:23.3.0 -> 26.1.0 (*)
+--- xsl.common:ad:1.0.6
|    +--- xsl.common:base:2.0.0-SNAPSHOT -> 2.1.6 (*)
|    \--- xsl.common:usercenter:2.2.1 -> 3.4.0 (*)
+--- xsl.common:cloud:1.0.5
|    +--- com.qiniu:qiniu-android-sdk:7.2.1
|    |    +--- com.qiniu:happy-dns:0.2.7
|    |    \--- com.squareup.okhttp3:okhttp:3.2.0 -> 3.4.2 (*)
|    \--- com.alibaba:fastjson:1.2.8 -> 1.2.46
+--- xsl.common:discussioncircle:1.0.10
|    +--- xsl.common:imageloader:1.0.2 -> 1.0.3
|    |    \--- com.android.support:appcompat-v7:24.2.1 -> 26.1.0 (*)
|    \--- org.zeroturnaround:zt-zip:1.8
|         \--- org.slf4j:slf4j-api:1.6.6
+--- xsl.common:usercenter:3.4.0 (*)
+--- xsl.common:revenue:1.2.5
|    \--- com.android.support:appcompat-v7:26.1.0 (*)
+--- xsl.common:base:2.1.6 (*)
+--- xsl.reactive:react-native-kit:1.7.1
|    \--- com.android.support:appcompat-v7:26.1.0 (*)
+--- xsl.webview:core:1.5.5
|    +--- xsl.common:audio:1.2.4
|    |    \--- com.android.support:appcompat-v7:26.1.0 (*)
|    +--- xsl.webview:image:1.4.13
|    |    +--- com.android.support:appcompat-v7:26.1.0 (*)
|    |    +--- com.github.chrisbanes.photoview:library:1.2.4 (*)
|    |    \--- com.android.support.constraint:constraint-layout:1.0.2
|    |         \--- com.android.support.constraint:constraint-layout-solver:1.0.2
|    \--- com.android.support:appcompat-v7:26.1.0 (*)
+--- xsl.common:persistent-connection:2.0.0-SNAPSHOT
+--- xsl.common:imageloader:1.0.3 (*)
+--- xsl.common:umengshare:3.0.0
+--- xsl.business:core:0.0.3
+--- com.squareup.retrofit2:adapter-rxjava:2.0.2
|    +--- com.squareup.retrofit2:retrofit:2.0.2 (*)
|    \--- io.reactivex:rxjava:1.1.1 -> 1.3.0
+--- com.squareup.retrofit2:retrofit:2.0.2 (*)
+--- com.squareup.retrofit2:converter-gson:2.0.2 (*)
+--- com.jakewharton.rxbinding:rxbinding:0.4.0
|    +--- io.reactivex:rxandroid:1.1.0
|    |    \--- io.reactivex:rxjava:1.1.0 -> 1.3.0
|    +--- io.reactivex:rxjava:1.1.0 -> 1.3.0
|    \--- com.android.support:support-annotations:23.1.0 -> 24.2.1
+--- de.greenrobot:eventbus:2.4.0
+--- com.android.support:multidex:1.0.3
+--- io.reactivex.rxjava2:rxandroid:2.0.1
|    \--- io.reactivex.rxjava2:rxjava:2.0.1
|         \--- org.reactivestreams:reactive-streams:1.0.0
+--- com.facebook.stetho:stetho-okhttp3:1.5.0
|    +--- com.facebook.stetho:stetho:1.5.0
|    |    +--- commons-cli:commons-cli:1.2
|    |    \--- com.google.code.findbugs:jsr305:2.0.1 -> 1.3.9
|    +--- com.google.code.findbugs:jsr305:2.0.1 -> 1.3.9
|    \--- com.squareup.okhttp3:okhttp:3.4.2 (*)
+--- com.squareup.okhttp3:logging-interceptor:3.4.1
|    \--- com.squareup.okhttp3:okhttp:3.4.1 -> 3.4.2 (*)
+--- com.czt.mp3recorder:library:1.0.2
|    \--- com.android.support:support-v4:23.1.1 -> 26.1.0 (*)
+--- com.android.support:appcompat-v7:26.1.0 (*)
+--- com.android.support:design:26.1.0
|    +--- com.android.support:support-v4:26.1.0 (*)
|    +--- com.android.support:appcompat-v7:26.1.0 (*)
|    +--- com.android.support:recyclerview-v7:26.1.0
|    |    +--- com.android.support:support-annotations:26.1.0 -> 24.2.1
|    |    +--- com.android.support:support-compat:26.1.0 (*)
|    |    \--- com.android.support:support-core-ui:26.1.0 (*)
|    \--- com.android.support:transition:26.1.0
|         +--- com.android.support:support-annotations:26.1.0 -> 24.2.1
|         \--- com.android.support:support-v4:26.1.0 (*)
+--- com.github.chrisbanes.photoview:library:1.2.4 (*)
+--- com.jakewharton:butterknife:8.8.1
|    +--- com.jakewharton:butterknife-annotations:8.8.1
|    |    \--- com.android.support:support-annotations:25.3.0 -> 24.2.1
|    +--- com.android.support:support-annotations:25.3.0 -> 24.2.1
|    \--- com.android.support:support-compat:25.3.0 -> 26.1.0 (*)
+--- com.android.support:support-v4:26.1.0 (*)
+--- com.alibaba:fastjson:1.2.46
+--- com.umeng.analytics:analytics:latest.integration -> 6.1.4
+--- com.afollestad.material-dialogs:commons:0.9.0.2
|    +--- com.android.support:appcompat-v7:24.2.1 -> 26.1.0 (*)
|    \--- com.afollestad.material-dialogs:core:0.9.0.2
|         +--- com.android.support:support-v4:24.2.1 -> 26.1.0 (*)
|         +--- com.android.support:appcompat-v7:24.2.1 -> 26.1.0 (*)
|         +--- com.android.support:recyclerview-v7:24.2.1 -> 26.1.0 (*)
|         +--- com.android.support:support-annotations:24.2.1
|         \--- me.zhanghai.android.materialprogressbar:library:1.1.7
|              +--- com.android.support:appcompat-v7:24.0.0 -> 26.1.0 (*)
|              \--- com.android.support:support-annotations:24.0.0 -> 24.2.1
+--- com.birbit:android-priority-jobqueue:2.0.1
|    +--- com.squareup.okio:okio:1.8.0 -> 1.9.0
|    \--- com.android.support:support-v4:21.0.3 -> 26.1.0 (*)
+--- com.meituan.android.walle:library:1.1.5 (*)
+--- com.android.support.constraint:constraint-layout:1.0.2 (*)
+--- io.reactivex:rxjava:1.3.0
+--- io.reactivex:rxandroid:1.1.0 (*)
+--- cn.aigestudio.wheelpicker:WheelPicker:1.1.2
+--- com.android.support:cardview-v7:26.1.0
|    \--- com.android.support:support-annotations:26.1.0 -> 24.2.1
+--- xsl.cooperation:core:1.0.0-SNAPSHOT
|    \--- com.android.support:appcompat-v7:25.3.1 -> 26.1.0 (*)
+--- com.android.support:gridlayout-v7:26.1.0
|    +--- com.android.support:support-compat:26.1.0 (*)
|    \--- com.android.support:support-core-ui:26.1.0 (*)
+--- me.drakeet.multitype:multitype:3.0.0
|    +--- com.android.support:support-annotations:25.3.1 -> 24.2.1
|    \--- com.android.support:recyclerview-v7:25.3.1 -> 26.1.0 (*)
+--- q.rorbin:badgeview:1.1.2
+--- com.yanzhenjie:permission:1.1.2
|    +--- com.android.support:appcompat-v7:25.3.1 -> 26.1.0 (*)
|    \--- com.yanzhenjie.alertdialog:alertdialog:1.0.1
|         \--- com.android.support:appcompat-v7:25.3.1 -> 26.1.0 (*)
+--- com.yanzhenjie:recyclerview-swipe:1.1.3
|    +--- com.android.support:recyclerview-v7:25.3.1 -> 26.1.0 (*)
|    \--- com.yanzhenjie:loading:1.0.2
+--- xsl.common:xDesign:0.0.16
+--- org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.30
|    \--- org.jetbrains.kotlin:kotlin-stdlib:1.2.30
|         \--- org.jetbrains:annotations:13.0
+--- com.squareup.leakcanary:leakcanary-android-no-op:1.5.1
\--- com.android.support:multidex:1.0.2 -> 1.0.3

依赖图:

https://github.com/vanniktech/gradle-dependency-graph-generator-plugin

依赖冲突

多个依赖引用同一个库的不同版本很常见,导致打包过程出现以下错误:

  • com.android.build.api.transform.TransformException:
  • java.util.zip.ZipException: duplicate entry:

针对这些问题,gradle 做了一些优化,

1 默认使用项目中引用的最高版本,

2 修改默认策略,如果由版本冲突,就构建失败

configurations.all {  
    resolutionStrategy {
        failOnVersionConflict()
    }
}

3 强制指定一个版本

configurations.all {  
    resolutionStrategy {
        failOnVersionConflict()
        force 'com.xxx.xx:0.0.1'
    }
}
  1. 如果模块冲突可以通过语法强制选择一个版本。
configurations.all {  
  resolutionStrategy {
    preferProjectModules()
  }
}
  1. 排除传递性依赖
dependencies {  
    compile('com.android.support:appcompat-v7:23.1.0') {
        exclude group: 'com.parse.bolts'
    }
}

6.替换依赖

configurations.all {  
  resolutionStrategy {
    dependencySubstitution {
      substitute module('commons-io:commons-io:2.4') with project(':my-commons-io')
    }
  }
}

7.通过 implementation compileOnly 等方式不向上传递依赖。

API & implementation

Gradle plugin 3.x.x 之后,Java Library plugin 废弃 compile/provided等依赖方式,改为 API/Implementation,优化依赖模式,增加编译时依赖、运行时依赖能力

dependencies {  
    api 'commons-httpclient:commons-httpclient:3.1'
    runtimeOnly 'com.android.support:appcompat-v7:23.1.1' 
    compileOnly 'commons-httpclient:commons-httpclient:3.1'
    implementation 'org.apache.commons:commons-lang3:3.5'
}

api会将依赖暴露给消费者,而 implemtation 仅供内部使用,使用implemtation好处

  • dependencies do not leak into the compile classpath of consumers anymore, so you will never accidentally depend on a transitive dependency

  • faster compilation thanks to reduced classpath size

  • less recompilations when implementation dependencies change: consumers would not need to be recompiled

  • cleaner publishing: when used in conjunction with the new maven-publish plugin, Java libraries produce POM files that distinguish exactly between what is required to compile against the library and what is required to use the library at runtime (in other words, don’t mix what is needed to compile the library itself and what is needed to compile against the library).

implemtation&api 对比:

依赖原则

  • 添加依赖前分析方法数、大小
  • 删除依赖前确认公共库引用
  • 编写公共库需要保证版本的向下兼容性。
  • Maven 上传jar/aar 包,debug版上传至 SnapShot/Debug 后缀。
  • 避免通过「版本+」的方式自动引入最新版本公共库。

https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#new_configurations

https://docs.gradle.org/current/userguide/javalibraryplugin.html

张鹏宇

继续阅读此作者的更多文章