摘要:本文将带你了解Android应用开发Android - Understanding and dominating gradle dependencies,希望本文对大家学Android有所帮助。
本文将带你了解Android应用开发Android - Understanding and dominating gradle dependencies,希望本文对大家学Android有所帮助。
Android - Understanding and dominating gradle dependencies
From
https://www.devsbedevin.com/android-understanding-gradle-dependencies-and-resolving-conflicts/
My latest post discussed gradle'sdependencyInsighttask. let's pe deeper into dependencies, direct and transitive, and gradle's dependency tools.
Direct VS. Transitive
Transitive dependency is an implied dependency, allowing your project to depend on libraries that depend on other libraries. The result is a dependency tree. These trees tend to get complex as your project requires more and more libraries to compile.
A direct, or "first level" dependency is one that you the developer explicitly import.
Exploring the dependency tree
We'll get back to transitive dependencies in a second. For now let's look at a project's entire dependency tree.
Invokinggradle dependencies --configuration compileresults in something like this:
Already we can learn that this project has a lot of dependency conflicts. Those are marked by
{library name}:{required version} -> {actual version}
Conflicts
It is very common for for different modules and libraries to share the same dependencies. Who doesn't useapache-commonsandGSon Huh folks Am I right This guy knows what I'm talking about.
A problem arises when the dependency is the same, but each module or library expects a different version. This causes the project to contain multiple versions of the same class, and in turn causes the Dex tool to fail with the following error:
com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry:
Resolving conflicts
If we didn't have gradle's transient dependency management, we would have to manually keep track of each dependency and resolve version conflicts by hand. This becomes harder the larger your project is. Lucky us we have gradle to handle the headache in one of several ways:
The default behaviour is to settle on the newest version of the requested dependency. Please mind the wordnewestas opposed tohighest version requested. This is fine as long as the versions are backward compatible with the lowest version your project expects.
Second most popular resolution is to fail the build. You, the developer, would have to resolve the conflicts yourself.
Configuring a first level dependency as forced is useful in cases where the conflicted transient dependency is already a direct (=first level) dependency.
You may also configure a transient dependency as forced, thus forcing your entire project to settle on a specific version.
If your build contains custom forks of the conflicted dependency, you may force gradle to use your own modules.
You may tell gradle to not resolve transient dependencies of a specific library at all. Of course you would need to rely instead on manually added direct dependencies and/or existing transient ones.
You may as well exclude specific transient dependencies referenced by a direct one.
Configuring build.gradle
The aforementioned strategies do not always translate directly to configuration switches.
Let's go over the basic techniques in achieving what we want:
Controlling dependencies project wide
This is achieved via theresolutionStrategyartifact.
Failing on version conflict
Add the following to your main project'sbuild.gradlefile.
configurations.all {
resolutionStrategy {
failOnVersionConflict()
}
}
Forcing a specific dependency
The following example forcesasm-all 3.3.1,commomns-io 1.4, and latestboltswhere the major version number is 1 (i.e. bolts 1.x):
configurations.all {
resolutionStrategy {
force 'asm:asm-all:3.3.1', 'commons-io:commons-io:1.4', 'com.parse.bolts:bolts-android:1.+'
}
}
Preferring own modules
Always prefer own modules:
configurations.all {
resolutionStrategy {
preferProjectModules()
}
}
Replace all instances ofcommons-iowith a custom modulemy-commons-io:
configurations.all {
resolutionStrategy {
dependencySubstitution {
substitute module('commons-io:commons-io:2.4') with project(':my-commons-io')
}
}
}
Controlling specific dependencies
You may also fine grain your settings to a specific dependency on a specific project.
Excluding transient dependencies
Adding this to your dependencies tag would add the libraryappcompat-v7but none of its own transient dependencies. You will have to make sure that all of the libraries needed dependencies are added either by adding direct dependencies yourself or by relying on transient dependencies referenced by other modules:
dependencies {
compile('com.android.support:appcompat-v7:23.1.0') {
transitive = false
}
}
The default fortransitiveistrue.
You can also exclude specific transient dependencies. The following example excludes theboltslibrary from being added, if needed byappcompat:
dependencies {
compile('com.android.support:appcompat-v7:23.1.0') {
exclude group: 'com.parse.bolts'
}
}
Forcing a specific version
This forces your project to settle onboltsversion 1.1:
dependencies {
compile('com.parse.bolts:bolts-android:1.+') {
force = true
}
}
TL;DR
Controlling dependencies project wide
Example taken from gradle'sofficial docs:
configurations.all {
resolutionStrategy {
// fail eagerly on version conflict (includes transitive dependencies)
// e.g. multiple different versions of the same dependency (group and name are equal)
failOnVersionConflict()
// prefer modules that are part of this build (multi-project or composite build) over external modules
preferProjectModules()
// force certain versions of dependencies (including transitive)
// *append new forced modules:
force 'asm:asm-all:3.3.1', 'commons-io:commons-io:1.4'
// *replace existing forced modules with new ones:
forcedModules = ['asm:asm-all:3.3.1']
// add dependency substitution rules
dependencySubstitution {
substitute module('org.gradle:api') with project(':api')
substitute project(':util') with module('org.gradle:util:3.0')
}
// cache dynamic versions for 10 minutes
cacheDynamicVersionsFor 10*60, 'seconds'
// don't cache changing modules at all
cacheChangingModulesFor 0, 'seconds'
}
}
Controlling specific dependencies
dependencies {
// We load commons-io but none of its transient dependencies
compile('commons-io:commons-io:2.4') {
transitive = false
}
// We exclude bolts altogether from appcompat's transient dependencies
compile('com.android.support:appcompat-v7:23.1.0') {
exclude group: 'com.parse.bolts'
}
// Force a specific version
compile('com.parse.bolts:bolts-android:1.+') {
force = true
}
}
Exploring dependencies
To review all of your project's dependencies:
gradle dependencies --configuration CONFIGURATION_NAME
To inspect a specific dependency (more on this inthis post):
gradle -q dependencyInsight --configuration CONFIGURATION_NAME --dependency DEPENDENCY_NAME
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号