简体   繁体   中英

Dependency management between modules

If I have module A and module B that both needs a JSON library (say GSON), and then I have application C which includes module A & B. There is a chance I will get two different versions of the JSON library if module A and B use different versions? Or does gradle remove one of them and just use one of the versions?

What if I have even more modules, updating them to use the same version of a dependency seems like a lot of work. In this case, letting Application C decide which version to use over all modules would be nice (but not always working I guess because of backwards compatability). Anyway to achieve this?

So my questions is how to best handle dependencies which are very common in many modules. Should I have a Json wrapper that I inject in all my modules instead, letting the Application define what to use?

I guess logging could be a similar dependency

Yes. If you specifically ask for different versions of the same library in projects A and B, you might end up with different versions of the same direct dependency.

As to transient dependencies, the default behaviour is to settle on the newest version of the requested dependency. Please mind the word newest as opposed to highest version requested. This is fine as long as the versions are backward compatible with the lowest version your project actually expects.

Luckily, gradle has several built in methods to settle dependency conflicts.

I have written extensively on the subject here: http://www.devsbedevin.net/android-understanding-gradle-dependencies-and-resolving-conflicts/

TL;DR

You may choose to fail on conflicts:

configurations.all {  
  resolutionStrategy {
    failOnVersionConflict()
  }
}

Force a specific dependency:

configurations.all {  
  resolutionStrategy {
    force 'asm:asm-all:3.3.1', 'commons-io:commons-io:1.4', 'com.parse.bolts:bolts-android:1.+'
  }
}

Prefer your own modules:

configurations.all {  
  resolutionStrategy {
    preferProjectModules()
  }
}

Replace all instances of libary X with Y (either a library, a module or a project):

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

Exclude all transient dependencies for a specific library and add the necessary libraries by manually:

dependencies {  
    compile('com.android.support:appcompat-v7:23.1.0') {
        transitive = false
    }
}

Exclude a specific transitive dependency:

dependencies {  
    compile('com.android.support:appcompat-v7:23.1.0') {
        exclude group: 'com.parse.bolts'
    }
}

Force your project to use a specific version regardless of the actual dependency requirements:

dependencies {  
    compile('com.parse.bolts:bolts-android:1.+') {
        force = true
    }
}

Consider a Gradle build that has two modules/projects. The settings.gradle file:

include 'modA', 'modB'

Let's say that both use commons-lang3-3.6 , and modA uses gson-2.8.1 , whereas modB uses gson-2.2.4 . One could configure this in the build.gradle file at the root:

subprojects { p ->
    apply plugin: 'java'

    repositories {
        jcenter()
    }
    dependencies {
        compile 'org.apache.commons:commons-lang3:3.6'
    }

    if (p.name == 'modA') {
        dependencies {
            compile 'com.google.code.gson:gson:2.8.1'
        }
    } else if (p.name == 'modB') {
        dependencies {
            compile 'com.google.code.gson:gson:2.2.4'
        }
    }
}

The desired config can be confirmed with:

$ gradle :modA:dependencies
$ gradle :modB:dependencies

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM