Manage your Gradle dependencies with Version Catalog (not only) in Android

Łukasz Bogusz
Source Diving
Published in
3 min readOct 15, 2021

--

If you ever built a single module Android app, you probably managed your dependencies manually. We all started there. Then as you move to a multi-module setup, you realize it doesn’t work anymore and shiny highlights and convenient shortcuts from your IDE don’t really make your life easier, if you have to go through all the modules in your project to update dependencies. So you find yourself a better solution using ext blocks or even a buildSrc. You might want to take a quick recap and read this great summary. However with Gradle 7.0 there is a new player in town that can be another alternative.

Where do I start?

First and foremost, you have to opt into VERSION_CATALOG feature preview in your settings.gradle:

enableFeaturePreview("VERSION_CATALOGS")

That’s pretty much everything you need to start defining dependencies in your catalog. You can carry on in that file with the dependency definition specifying its version, alias or bundle:

dependencyResolutionManagement {
versionCatalogs {
libs {
version('ver', '1.0.0')
alias('my-alias').to('group', 'artifact').versionRef('ver')
alias('another').to('group', 'artifact').versionRef('ver')
bundle('my-bundle', ['my-alias', 'another'])
}
}
}

This enables you to use your alias or bundle across the project as libs.my.alias or bundle.my.bundle in the .gradle files. Alias represents a single dependency while bundle can incorporate as many dependencies as you want. Version catalogs support autocompletion in the IDE through their type-safe accessors generated by Gradle.

You probably noted that character is replaced by . for the catalog. Separators such as -, _, . create subsections and subsection can not be a name on its own. This means that you can’t have alias('dagger') and alias('dagger-android') so you will likely go with alias('dagger-core') instead. You can read more about type safe accessors in the official documentation.

Structured catalog with TOML files

Although you might define versions, aliases, bundles and plugins in one place settings.gradle, the beauty of version catalog comes from the ability to split your dependencies in a more structured manner. They can be declared in .toml files and by default Gradle will use gradle/libs.versions.toml as the input for libs catalog. All you need is to create this file in your repository declaring [versions], [libraries], [bundles] , [plugins] and following structure:

The access for each section is the same as you would define it within a .gradle file. You can use each section item alone and here are some examples of how you might want it:

// Access versions in your top build.gradle
buildscript {
...
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlin.get()}"
}
}
// Access versions in the android block
composeOptions {
kotlinCompilerExtensionVersion androidx.versions.compose.core.get()
kotlinCompilerVersion libs.versions.kotlin.get()
}
// Implement a single dependency
implementation libs.google.material
// Implement the whole bundle
implementation libs.bundles.accompanist
// Use with annotationProcessor or kapt
annotationProcessor libs.room.compiler

I want more catalogs

Default libs catalog is quite convenient but when your start defining your dependencies you might want to give more meaning to the libs subsection. You can override its name through defaultLibrariesExtensionName, but more importantly you can import another catalog to the project.

Newly created catalog can be accessed similarly to the default one:

// Implement a single dependency 
implementation androidx.lifecycle
// Implement the whole bundle
implementation androidx.bundles.base
implementation androidx.bundles.compose

Version updates (bonus)

Unfortunately, there is no support for versions update at the moment. If a new version of a dependency arrives, the IDE will not highlight outdated versions, but neither do you have this with ext blocks. However, that doesn’t mean there is no tool to support that. You can grab the Gradle version plugin from Ben Manes and adjust it to your needs:

--

--