Blog Infos
Author
Published
Topics
,
Author
Published
Posted by: Satya Pavan Kantamani

Change your Android build scripts to Kotlin DSL for better flexibility

Introduction

In Android Studio the build Gradle files in our project structure by default use Groovy build language. We basically define dependencies, plugins, project settings, etc in our Gradle files. As we are busy with our development tasks and timelines we don’t take space to know more about them. And writing code in these Gradle files doesn’t seem excited because we are not well versed with Groovy.

In this post let’s explore What is a DSL and the Kotlin DSL migration journey from Groovy DSL.

What is a DSL?

DSL is an acronym for Domain Specific Language that can be used in the context of a particular domain. It’s a contrast to General-Purpose Language (GPL) like Java which is widely applicable or used for multiple domains. It helps us to write declarative code to reduce the boilerplate stuff. The code written with DSL would be much easier to read.

The common usage of DSL language is HTML in Web development, Gradlein build tools, SQL in data management, XML for the Markup language, etc. Though we might have experience in above mentioned one or more languages but we might not know that we are using DSL.

Gradle

Gradle is a powerful build tool. Gradle provides a domain-specific language, or DSL, for describing builds scripts. Gradle provides support for Groovy and Kotlin domain-specific language or DSL, for describing builds. A Groovy build script can contain any Groovy language element. A Kotlin build script can contain any Kotlin language element.

As most of us are using Kotlin for development it would be easy and flexible to have build scripts in Kotlin rather than Groovy. Now let’s move to Kotlin DSL details.

Kotlin DSL

Kotlin DSL is built on top of the core language Kotlin. So the syntax would no different from the parent language which gives us the benefit of using Kotlin for development. Kotlin DSL is fully supported in Android Studio.

Gradle’s Kotlin DSL provides an alternative syntax to the traditional Groovy DSL with an enhanced editing experience in supported IDEs, with superior content assist, refactoring, documentation, and more — Gradle Team

We can have few benefits from choosing Kotlin DSL over Groovy

  1. Good readability
  2. Easily adaptable Kotlin syntax from the parent language
  3. Code Navigation and auto suggestions
  4. Compile-time time errors
  5. Currently supports type-safe model accessors for Dependency and artifact configurations, source sets, etc

But it might be a bit slower in some situations like clean, buildSrc directory related changes, etc

Migrating build scripts from Groovy to Kotlin

Before starting migration let’s go through some default things

From Gradle Docs

  • Groovy strings can be quoted with single quotes 'string' or double quotes "string" whereas Kotlin requires double quotes "string".
  • Groovy allows omitting parentheses when invoking functions whereas Kotlin always requires the parentheses.
  • The Gradle Groovy DSL allows omitting the = assignment operator when assigning properties whereas Kotlin always requires the assignment operator.

Let’s get started with conversions. In this post let’s convert build.gradle and settings.gradle file to .gradle.kts

First of all rename .gradle files to .gradle.kts (Groovy DSL script files use the .gradle file name extension & Kotlin DSL script files use the .gradle.kts file name extension)

Step 1

Let’s refractor settings.gradle to settings.gradle.kts

//Before
include ':app', ':sampleModule'
//After
include(":app", ":sampleModule")
view raw sett.gradle.kts hosted with ❤ by GitHub
Step 2

Now let’s migrate project-level build.gradle to build.gradle.kts. The default root or project-level build.gradle generated will be looking as below

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.5.0"
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
view raw toplevel.gradle hosted with ❤ by GitHub

As we observe the code initial part is variable decleration

ext.kotlin_version = "1.5.0"

which will be changed to

val kotlin_version = "1.5.0"

Skipping repositories part let’s move to the classpath. Specifying functions using classpath to add dependencies to the script

classpath "com.android.tools.build:gradle:4.2.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

But with Kotlin DSL specifying function would as following

classpath ("com.android.tools.build:gradle:4.2.1")
classpath ("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")

By applying the specified rules mentioned above the complete will be changed as below. Take a closer look to understand the differences.

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
val kotlin_version = "1.5.0"
repositories {
google()
mavenCentral()
}
dependencies {
classpath ("com.android.tools.build:gradle:4.2.1")
classpath ("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
tasks.register("clean", Delete::class){
delete(rootProject.buildDir)
}

As we are done with project-level gradle file let’s move to app-level gradle file

Hier noch einige Links

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

Jobs

Step 3

Now let’s migrate app-level build.gradle to build.gradle.kts. The default app-level build.gradle generated will be looking as below

plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.sample.myapplication"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

After migration it will be looking as:

plugins {
id("com.android.application")
kotlin("android")
}
android {
compileSdkVersion(30)
buildToolsVersion("30.0.3")
defaultConfig {
applicationId = "com.sample.dsl"
minSdkVersion(21)
targetSdkVersion(30)
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
}
}
}
dependencies {
implementation("androidx.core:core-ktx:1.5.0")
implementation("androidx.appcompat:appcompat:1.3.0")
implementation("com.google.android.material:material:1.3.0")
implementation("androidx.constraintlayout:constraintlayout:2.0.4")
testImplementation("junit:junit:4.+")
androidTestImplementation("androidx.test.ext:junit:1.1.2")
androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0")
}

More or less both look similar but Kotlin files can give better readability. There would be minor changes

  • Like for release type we need to use getByName(“release”) rather than release
  • And assignment of values like versionCode = 1 rather thanversionCode 1
  • there would be name changes for properties like isMinifyEnabled rather than minifyEnabled and few other

This post was just a start to understand about Kotlin DSL there are many more things that we can do. Let’s see much more in upcoming posts.

Summary

Kotlin DSL is comparatively easy and has good cons when compared with Groovy. Parent Kotlin language syntax will always be beneficial. I would recommend using Kotlin DSL though it’s a bit slower in some cases. It would in well readable format once you have migrated your build files. We can have interoperability with Groovy code but to some extent.

Let’s learn about better dependency management using buildSrc in Kotlin DSL in the next post. Don’t forget to clap if you found this article helpful.

References
Continue Reading Android Stuff

Understand How View Renders in Android

The Life Cycle of a View in Android

Kotlin Series

How to Implement In-App Purchases in Your Android App

Many More

Tags: Android, AndroidDev, Programming, Kotlin

 

View original article at:


Originally published: June 20, 2021

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
blog
Automation is a key point of Software Testing once it make possible to reproduce…
READ MORE
blog
Drag and Drop reordering in Recyclerview can be achieved with ItemTouchHelper (checkout implementation reference).…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu