Skip to main content
Donovan LaDuke - Developer

Manage Dependencies with Gradle BOMs


Featured in Android Weekly Issue 593

When working with libraries with many dependencies, such as Jetpack Compose or Koin, it can be difficult to ensure the dependencies are all using versions that are compatible. Thankfully, many of these large libraries will expose a Maven Bill of Materials (BOM) to streamline the consumption of their dependencies. This allows developers to target a single version number and know that when a dependency in that BOM is requested, they will get one that is compatible.

Example #

A build.gradle file for a project using Compose might include a few lines like this.

implementation("androidx.compose.ui:ui:1.5.0")
implementation("androidx.compose.animation:animation:1.5.3")
implementation("androidx.compose.material3:material3:1.1.2")

There is no way just from looking at the above to know if the versions are correct or compatible. Since Compose exposes a BOM, the code can be updated to leverage the BOM and avoid the ambiguity.

implementation(platform("androidx.compose:compose-bom:2023.10.00"))

implementation("androidx.compose.ui:ui")
implementation("androidx.compose.animation:animation")
implementation("androidx.compose.material3:material3")

Now the versions will all be determined by the BOM. If the Compose dependency needed to be updated in the future, the BOM version is the only thing that needs updated and the rest of the dependencies will get that set of version updates.

Overrides #

If a different version of a specific dependency is needed, it is as simple as specifying the version of that dependency. The specific requested version will override the BOM version and be used instead. This does void the trust from the BOM that all the dependencies will work together, but is required on occasion; e.g. needing features only available in an alpha version.

implementation(platform("androidx.compose:compose-bom:2023.10.00"))

// Loads From BOM
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.animation:animation")

// Loads 1.2.0-alpha09 Explicitly
implementation("androidx.compose.material3:material3:1.2.0-alpha09")

Using a BOM in with Version Catalog #

Using a BOM with Gradle version catalogs is equally simple. Just define the BOM in the libs.versions.toml file and define the dependencies without a version to use the BOM.

[versions]
compose-bom = "2023.03.00"
compose-material3 = "1.2.0-alpha09"

[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }

// Leverage BOM
ui = { group = "androidx.compose.ui", name = "ui" }
animation = { group = "androidx.compose.animation", name = "animation" }

// Override BOM
material3 = { group = "androidx.compose.material3", name = "material3" , version.ref = "compose-material3"}

Then, add the BOM to the build.gradle and import the other dependencies as usual.

implementation(platform(libs.compose.bom))
implementation(libs.ui)
implementation(libs.animation)
implementation(libs.material3)

Conclusion #

Leveraging a BOM makes consuming large modular libraries much simpler. This ensures the requested dependencies will all work together and will save developers time searching for obscure version conflict bugs or having to review a spreadsheet outlining the compatible versions every time a library is updated. Until next time, thanks!

Did you find this content helpful?

Please share this post and be sure to subscribe to the RSS feed to be notified of all future articles!

Want to go above and beyond? Help me out by sending me $1 on Ko-fi. It goes a long way in helping run this site and keeping it advertisement free. Thank you in advance!

Buy me a Coffee on Ko-fi