Chema Rubio

@develodroid

Android — How to add Gradle dependencies using ‘foreach’

A big project in Android with several modules also has several Gradle files that need to be configured, and that´s a tedious task. Something that is usually done is adding dependencies to each module, in this post it will be explained how to control all modules dependencies using just a single Gradle file.

Our goal is transforming this file

into this one

Dependencies File

In order to get this transformation done, first create a file to control all the project dependencies.

Create a file called dependencies.gradle inside root projet, and specify all the library versions that will be used.

Once it is done, let´s create the dependencies definition maps. In order to make the file as much organized as possible, three maps will be defined: one for the Android libraries, another one for third party libraries and the last one for testing libraries.

This is how the file should look like

Now each module needs a list to be created containing all dependencies needed respectively.

As an example, having a module called app that will use AppCompat, Dagger, RxJava and RxAndroid following list is defined.

Each object from the list contains a map defining the dependency and a configuration for it. In this example “compile” and “apt” configurations are used but there are much more such as “provided”, “testCompile”, “androidTestCompile”, etc…

Now open app module´s gradle file and use the following code.

How does this works? (◔_◔)?

Usually adding a dependency inside dependencies block looks like the following.

compile 'com.google.code.gson:gson:2.7'

DependencyHandle object add method it´s being directly called.

Let´s take a look to the add method.

add(String configurationName, Object dependencyNotation)
Adds a dependency to the given configuration.

This method takes as first parameter the configuration name (compile, testCompile, androidTestCompile…) and as second parameter the dependency itself.

Dependency may be defined the regular way as a String variable.

'com.google.code.gson:gson:2.7'

If using last Gradle versions (the way Android Studio does) it may be defined as a map.

[group: ‘com.google.code.gson’, name: ‘gson’, version: '2.7']

Going back with the code…

appDependencies list created before is being iterated, each iteration adds a dependency and its configuration. To represent current element in the iteration with Groovy use ‘it’ variable.

This process should be repeated in each module´s build.gradle file, this way anytime a new dependency is needed just add it to the corresponding list inside de dependencies file. This is how all dependencies will be controlled with just one file. Notice this file will be reusable in other Android projects.

Dependencies between modules

This process may be applied to add dependencies between modules.

To do so, inside dependencies.gradle all modules should be specified first. For example app, data and domain modules.

If app module will be using domain module, the dependency should be added the following way:

Options

If any additional options are needed such as excluding modules or using transitive, the regular way to do this was:

androidTestCompile ('com.android.support.test:runner:0.5') {
exclude module: 'support-annotations'
}

First thing to be done, is adding into the dependency an extra key-value to represent options. Let´s see this with an example:

Now, inside app module´s build.gradle file needs to be modified and change the add method so it adds a closure as an extra parameter in order to add options.

add(String configurationName, Object dependencyNotation, Closure configureClosure)
Adds a dependency to the given configuration, and configures the dependency using the given closure.

The build.gradle file should look like this:

Plugins

With this process is also possible to manage the plugins we use en each module and control all of them from dependencies.gradle file, let´s see an example in which this file

May be substituted by this one

Just create a list with the plugins that will be used by a module inside dependencies.gradle file.

Call dependencies.gradle

The way all this process would work, is calling dependencies.gradle file from build.gradle file located in the root project.

apply from: 'dependencies.gradle'

Check this example from a GitHub repository.

Disadvantages

Not everything in this process is beautiful, this way of adding an managing dependencies makes Android Studio incapable of notify when a library is out-to-date.

In order to solve this, you can mix both ways of adding and managing dependencies and using the regular way to manage Android libraries so it is notified when any library is out-to-date.

More by Chema Rubio

Topics of interest

More Related Stories