What I have in my build.gradle
:
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation 'com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.6'
The latter dependency has its own RecyclerView
transitive dependency:
implementation "androidx.recyclerview:recyclerview:1.2.1"
What I see then in the dependency tree is (for the RecyclerView
dependency I declared):
+--- androidx.recyclerview:recyclerview:1.1.0 -> 1.2.1
Also, in the code, I got the getBindingAdapterPosition
method, which appeared after 1.1.0.
Certainly, we should always try to use the latest version of the dependencies, but is it the correct behavior?!
I thought that transitive dependencies wouldn't override the declared ones.
What if my code relies on some functionality present in version 1.1.0 only?
The default behaviour is described in the doc:
Gradle resolves any dependency version conflicts by selecting the latest version found in the dependency graph.
You can enforce a certain version of a transitive dependency, excluding a dependency. Something like:
implementation('commons-beanutils:commons-beanutils:1.9.4') {
exclude group: 'commons-collections', module: 'commons-collections'
}
but please note that:
Excluding a dependency completely requires a conscious decision. Excluding a transitive dependency might lead to runtime errors if external libraries do not properly function without them. If you use excludes, make sure that you do not utilise any code path requiring the excluded dependency by sufficient test coverage.
You can also use a strict versions even if a transitive dependency says otherwise. Something like:
implementation('commons-codec:commons-codec') {
version {
strictly '1.9'
}
}
Also in this case note that:
Forcing a version of a dependency requires a conscious decision. Changing the version of a transitive dependency might lead to runtime errors if external libraries do not properly function without them.