Mastering Dependency Management- Android
As Android projects grow in size and complexity, managing dependencies across multiple modules becomes increasingly challenging. This comprehensive guide will explore different approaches to handling dependencies effectively, complete with practical examples and best practices.

1. Version Catalogs (Recommended Approach)
Version Catalogs, introduced in Gradle 7.0+, represent the modern approach to dependency management. They use the TOML format for better readability and provide type-safe accessors.
Setting up Version Catalogs
- First, create a
libs.versions.toml
file in your project'sgradle
directory:
[versions]
kotlin = "1.8.0"
compose = "1.4.0"
retrofit = "2.9.0"
room = "2.5.0"
hilt = "2.45"
[libraries]
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "compose" }
compose-material = { group = "androidx.compose.material", name = "material", version.ref = "compose" }
retrofit-core = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
[bundles]
compose = ["compose-ui", "compose-material"]
2. Enable version catalogs in your settings.gradle.kts
:
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("gradle/libs.versions.toml"))
}
}
}
3. Now you can use these dependencies in any module:
dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.bundles.compose)
implementation(libs.retrofit.core)
}
Benefits of Version Catalogs:
- Type-safe accessors
- IDE support with auto-completion
- Centralized version management
- Support for dependency bundles
- Clear, readable TOML format
2. buildSrc Directory
The buildSrc approach uses Kotlin code to manage dependencies, providing type safety and refactoring support.
Setting up buildSrc
- Create a
buildSrc
directory in your project root - Add
build.gradle.kts
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
3. Create Dependencies.kt
:
object Versions {
const val KOTLIN = "1.8.0"
const val COMPOSE = "1.4.0"
const val RETROFIT = "2.9.0"
}
object Deps {
const val kotlinStdLib = "org.jetbrains.kotlin:kotlin-stdlib:${Versions.KOTLIN}"
object Compose {
const val ui = "androidx.compose.ui:ui:${Versions.COMPOSE}"
const val material = "androidx.compose.material:material:${Versions.COMPOSE}"
}
object Network {
const val retrofit = "com.squareup.retrofit2:retrofit:${Versions.RETROFIT}"
}
}
4. Use in your modules:
dependencies {
implementation(Deps.kotlinStdLib)
implementation(Deps.Compose.ui)
implementation(Deps.Network.retrofit)
}
Benefits of buildSrc:
- Kotlin code with full IDE support
- Type safety and refactoring capabilities
- Automatic rebuilding when dependencies change
- Can include custom logic and extensions
3. Convention Plugins
Convention Plugins offer the most powerful approach for large projects, allowing you to share dependencies and configurations.
Creating Convention Plugins
- Set up the build-logic project:
// build-logic/convention/build.gradle.kts
plugins {
`kotlin-dsl`
}
dependencies {
implementation(libs.android.gradlePlugin)
implementation(libs.kotlin.gradlePlugin)
}
2. Create your convention plugin:
class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
pluginManager.apply {
apply("com.android.library")
apply("org.jetbrains.kotlin.android")
}
android {
compileSdk = 33
defaultConfig {
minSdk = 24
targetSdk = 33
}
dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.retrofit.core)
}
}
}
}
}
3. Use in your modules:
plugins {
id("com.android.library.convention")
}
Benefits of Convention Plugins:
- Share both dependencies and configurations
- Enforce standards across modules
- Provide reusable build logic
- Support complex setup and customizations
Best Practices
- Choose the Right Approach
- Use Version Catalogs for new projects
- Consider Convention Plugins for large, complex projects
- Use buildSrc when you need custom build logic
2. Version Management
- Keep versions separate from dependency declarations
- Use semantic versioning
- Document version changes
3. Organization
- Group related dependencies
- Use meaningful naming conventions
- Keep documentation updated
4. Maintenance
- Regularly update dependencies
- Monitor for security vulnerabilities
Tools to Help
- Gradle Version Catalog Update Plugin [ Link]
- Automatically checks for dependency updates
- Generates reports of available updates
2. Dependency Analysis Plugin [Link]
- Identifies unused dependencies
- Helps maintain clean dependency trees
Effective dependency management is crucial for maintaining healthy multi-module Android projects. Version Catalogs represent the modern, recommended approach, but buildSrc and Convention Plugins offer valuable alternatives for specific use cases. Choose the approach that best fits your project’s needs and team’s expertise.
Remember that good dependency management is an ongoing process. Regularly review and update your dependencies, monitor for security vulnerabilities, and maintain clean dependency trees. With these practices in place, your multi-module project will be more maintainable, scalable, and efficient.
What approach are you using in your Android projects? Have you tried Version Catalogs yet? Share your experiences in the comments below!