Centralizing Dependencies in Android Studio with Version Catalogs
Learn how Android Studio’s version catalogs let you declare library versions once in libs.versions.toml and reference them safely across modules. The guide walks through enabling catalogs, adding entries, using them in Kotlin DSL, and highlights common pitfalls and checks.
06 Jan 2026, 16:16 UTC

Why Version Catalogs Matter
In large Android projects, keeping track of library versions across dozens of modules can become a maintenance nightmare. Version catalogs let you define each dependency and its version in a single libs.versions.toml file. Gradle then generates type‑safe accessors that the IDE can autocomplete, reducing typos and making upgrades trivial.
Step 1 – Enable the Catalog in settings.gradle
Open the root settings.gradle (or settings.gradle.kts) and add the following block. This instructs Gradle to look for a libs.versions.toml file and generate the catalog accessors.
dependencyResolutionManagement {
enableVersionCatalogs = true
// Optional: specify a custom catalog name
// versionCatalogs { create("myLibs") }
}
After saving, trigger a Gradle sync. Android Studio will now create a libs.versions.toml file if it doesn’t exist.
Step 2 – Define Libraries in libs.versions.toml
The TOML file has three main sections: [versions], [libraries], and [bundles]. Below is a minimal example that adds androidx.core:core-ktx and a bundle for UI libraries.
[versions]
core-ktx = "1.10.1"
appcompat = "1.6.1"
material = "1.9.0"
[libraries]
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
[bundles]
ui = ["appcompat", "material"]
Notice how each library references a version by key, ensuring you only change the version in one place.
Step 3 – Reference the Catalog in Module Build Scripts
With the catalog enabled, you can use the generated libs namespace in any Gradle script. In a Kotlin DSL build.gradle.kts file, add:
dependencies {
implementation(libs.core.ktx)
implementation(libs.ui) // expands to appcompat and material
}
Android Studio will autocomplete libs. and show available entries. If you use the classic Groovy DSL, the syntax is implementation libs.core.ktx but you’ll need to add apply plugin: "org.gradle.plugin.devel"
to enable the catalog API.
Verification Checklist
- Sync after edits – Gradle must regenerate accessors; otherwise you’ll see unresolved symbol errors.
- Run
./gradlew :app:dependencies– Verify that the resolved version matches thelibs.versions.tomlentry. - Check IDE annotations – If a dependency is missing, the editor will underline
libs.core.ktxwith a red squiggle. - Inspect the generated catalog – In the Gradle pane, navigate to
Gradle > > Catalogs > libsto see the type‑safe objects.
Common Mistakes and How to Avoid Them
- Duplicate Declarations – Declaring a library both in the catalog and directly in
build.gradlecreates two entries on the classpath. Remove the direct reference and rely on the catalog. - Outdated Gradle Sync – After editing
libs.versions.toml, a sync is mandatory. Skipping it leads to build failures with “unresolved reference” errors. - Using Unsupported AGP or IDE – Version catalogs require AGP 7.0+ and Android Studio Flamingo (2022.2.1) or newer. Projects on older tooling will ignore the catalog.
- Custom Plugins Without Catalog Accessors – Some third‑party Gradle plugins may not expose catalog references. In those cases, fall back to the coordinate syntax until the plugin updates.
- Bundle Misuse – Bundles are collections of libraries; they cannot be used for transitive version overrides. Use them only for grouping.
Limitations to Keep in Mind
- Only Available in Kotlin DSL – While Groovy DSL support exists, many IDE features (e.g., autocomplete) are richer in Kotlin scripts.
- No Runtime Version Merging – The catalog does not merge conflicting transitive dependencies; you still need to manage conflicts manually.
- No Built‑in Version Conflict Resolution – If two modules reference different versions of the same library via the catalog, Gradle will still apply the usual conflict resolution rules.
- Catalog Scope – The catalog is project‑wide; if you need module‑specific overrides, you’ll have to edit the TOML or use
platform()dependencies.
Practical Example: Adding a New Library
Suppose you want to add kotlinx-coroutines-android:1.7.0. Follow these steps:
- Add the version to
[versions]:coroutines = "1.7.0" - Define the library:
coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" } - Sync the project.
- Reference it in a module:
dependencies { implementation(libs.coroutines.android) }
After a successful sync, the IDE will show the new library in the libs namespace, and the build will resolve to version 1.7.0 automatically.
Conclusion
Version catalogs streamline dependency management by centralizing versions, reducing duplication, and enabling IDE‑driven refactoring. Enabling them is a one‑time change that pays off as your project grows. Just remember to sync after edits, avoid duplicate declarations, and stay within the supported AGP/IDE versions.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.