Better dependencies management with Kotlin DSL — Scale your configuration

Umut TEKE
FrichtiTech
Published in
3 min readMar 23, 2021

Let’s see in this article, how to migrate to Gradle Kotlin DSL to properly centralize your Gradle dependencies.
DSL means Domain-Specific Language targeting to a particular kind of problem, rather than a general purpose language like Java aimed at any kind of software problem.
Thereby Kotlin DSL is a language dedicated to Gradle to build configuration in Kotlin instead of Groovy.

Why Gradle Kotlin DSL will benefit you ?

When you start developing in Kotlin, you could write your build configuration scripts in Kotlin. Groovy is not easy to manage.
In addition to the language, one of the main interests of this new syntax is the auto-completion offered by statically typed Kotlin. Unlike Groovy, which is dynamic, Android Studio struggles to set up the methods and parameters for you and reports input errors.
In order to take advantage of the new improvements made since version 3 of the Android plugin for Gradle, Google advises us to divide our projects into modules when our functional scope is sufficiently provided. This means that you have to manage the Gradle configurations in each module and keep control of the dependencies versions.

How do we usually start managing our dependencies ?

You probably started by adding dependencies manually which requires a lot of manual changes to updates libraries version.
Simple example of two modules feature_a and feature_b having some common dependencies.

feature_a/build.gradledependencies {
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.constraintlayout:constraintlayout:2.0.1"
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "com.airbnb.android:lottie:3.4.4"
}

feature_b/build.gradle
dependencies {
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.fragment:fragment-ktx:1.1.0"
implementation "androidx.transition:transition:1.3.1"
implementation "com.airbnb.android:lottie:3.4.4"
}

How to ensure that common dependencies have the same version ?

Google recommends to set extra properties in root build.gradle file for version centralization.
But we go further and go through the Kotlin configuration for Gradle which is more readable and friendly.

First we update root Gradle build configuration script to get kotlin plugin.

build.gradle.ktsbuildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle:4.0.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21")
}
}

allprojects {
repositories {
google()
jcenter()
}
}

tasks.register("clean", Delete::class){
delete(rootProject.buildDir)
}

Next, we create a new buildSrc module. This module is a Gradle feature allowing you to define tasks and tool kits to write build scripts.

We start to add a build configuration script file like any module.
However, this script is in Kotlin (with .kts extension for Kotlin Script) and we apply the Kotlin DSL plugin to it as shown below.

buildSrc/build.gradle.ktsplugins {
`kotlin-dsl`
}

repositories {
jcenter()
}

Next step, we create our Kotlin properties in a file that we could name Dependencies.kt to declare our dependencies and our versions.

buildSrc/src/main/kotlin/Dependencies.ktobject Versions {
const val appCompat = "1.2.0"
const val constraintLayout = "2.0.1"
const val recyclerView = "1.1.0"
const val transition = "1.3.1"
const val lottie = "3.4.4"
}

object Libraries {
val androidx = AndroidX
const val lottie = "com.airbnb.android:lottie:${Versions.lottie}"
}

object AndroidX {
const val appCompat = "androidx.appcompat:appcompat:${Versions.appCompat}"
const val constraintLayout = "androidx.constraintlayout:constraintlayout:${Versions.constraintLayout}"
const val recyclerView = "androidx.recyclerview:recyclerview:${Versions.recyclerView}"
const val transition = "androidx.transition:transition:${Versions.transition}"
}

The dependencies are more readable and enable centralization for better control.
Finally, start a Gradle synchronization. We can now access and apply our dependencies to the configuration scripts to the previous modules.

feature_a/build.gradle.ktsdependencies {   
implementation(Libraries.androidX.appCompat)
implementation(Libraries.androidX.constraintLayout)
implementation(Libraries.androidX.recyclerView)
implementation(Libraries.lottie)
}
feature_b/build.gradle.ktsdependencies {
implementation(Libraries.androidX.appCompat)
implementation(Libraries.androidX.fragment)
implementation(Libraries.androidX.transition)
implementation(Libraries.lottie)
}

See below an example of autocompletion displayed from Kotlin DSL.

Note that the transformation of your configuration scripts is not required. You can continue using Groovy combined with Kotlin DSL.

In conclusion, the DSL allows you to master your dependencies and have centralized management when your project takes on a larger scale.

--

--