Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Playing nice with Gradle - droidcon KE

Playing nice with Gradle - droidcon KE

Presentation given at droidcon KE, Nairobi, 2019

Abstract:
Gradle is the most popular build system in use today for building Android projects. It is an amazing tool that has improved how we build projects especially when we compare to the previous build systems used for Android development.

As your project starts to scale, so does the Gradle setup start to get complicated - from build performance, to configuring plugins, to managing dependencies, to managing multiple modules. Gradle by default makes use of Groovy language, which often does not provide the full features of static typing - hence making it more difficult to customize.

If like me, you’re in a love-hate relationship with Gradle, then, this talk is for you.

In this talk, we will go through top tips to make Gradle work for us as Android developers.

We will talk about different quick wins to make maintaining our Gradle configuration easy by:
avoiding repetitive code as your project modules continue to grow, and
writing your build configuration partly or fully in Kotlin, hence taking advantage of the Kotlin DSL feature.
You will leave this talk with a lot of ideas of how to improve the Gradle setup of your project.

Most of these ideas will be something you can immediately implement while some may require a little more effort. Ultimately we will be able to make Gradle work for you to achieve the best results.

Resource links in the slides:
https://handstandsam.com/2019/03/12/sharing-gradle-configuration-in-multi-module-android-projects/
https://segunfamisa.com/posts/android-gradle-extra-properties
https://gradle.com/blog/getting-started-with-gradle-kotlin-dsl/
https://github.com/gradle/kotlin-dsl
https://blog.codinghorror.com/rule-of-three/

9ab0b3b080e75e0c03a0c643333f8b93?s=128

Segun Famisa

August 09, 2019
Tweet

Transcript

  1. Playing nice with Gradle the elephant in the room Segun

    Famisa, Android GDE droidcon KE August, 2019
  2. @segunfamisa

  3. Outline • Introduction • Scenarios & improvements #0, #1, #2

    • Taking it a step further with Kotlin DSL • buildSrc • Migrating build scripts to Kotlin DSL from Groovy DSL • Kotlin DSL improvements • Resources
  4. Improving your gradle experience

  5. #0

  6. Small project, single or few modules #0

  7. // <app> build.gradle apply plugin: 'com.android.application' ... dependencies { ...

    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } #0
  8. // <networking-lib> build.gradle apply plugin: 'kotlin' ... dependencies { ...

    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } // <app> build.gradle apply plugin: 'com.android.application' ... dependencies { ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } #0
  9. // <app> build.gradle apply plugin: 'com.android.application' ... dependencies { ...

    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } // <networking-lib> build.gradle apply plugin: 'kotlin' ... dependencies { ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } #0
  10. #0 // <app> build.gradle apply plugin: 'com.android.application' ... dependencies {

    ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } // <networking-lib> build.gradle apply plugin: 'kotlin' ... dependencies { ... implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "io.reactivex.rxjava2:rxjava:2.2.5" } Managing dependencies versions becomes tedious
  11. #0 - solution

  12. #0 - solution Solving the duplication problem with Gradle extra

    (ext) properties feature
  13. // dependencies.gradle ext { ... libraries = [ rxJavaVersion :

    '2.2.5' rxAndroidVersion : '2.1.0' kotlinVersion : '1.3.31' ] } 1. Externalize dependencies
  14. 1. Externalize dependencies 2. Apply dependencies.gradle to root project //

    root build.gradle buildScript {...} allprojects {...} apply from: 'relative/path/to/dependencies.gradle'
  15. 1. Externalize dependencies 2. Apply dependencies.gradle to root project 3.

    Reference the dependencies in the build.gradle files // <app> build.gradle dependencies { ... def libs = rootProject.ext.libraries implementation "org.jetbrains.kotlin:...:$libs.kotlinVersion" implementation "io.reactivex.rxjava2:rxjava:$libs.rxJavaVersion" }
  16. 1. Externalize dependencies 2. Apply dependencies.gradle to root project 3.

    Reference the dependencies in the build.gradle files // <app> build.gradle dependencies { implementation "org.jetbrains.kotlin:...:$libs.kotlinVersion" implementation "io.reactivex.rxjava2:rxjava:$libs.rxJavaVersion" } // <networking-lib> build.gradle dependencies { ... def libs = rootProject.ext.libraries implementation "org.jetbrains.kotlin:...:$libs.kotlinVersion" implementation "io.reactivex.rxjava2:...:$libs.rxJavaVersion" }
  17. 1. Externalize dependencies 2. Apply dependencies.gradle to root project 3.

    Reference the dependencies in the build.gradle files // <app> build.gradle dependencies { implementation "org.jetbrains.kotlin:...:$libs.kotlinVersion" implementation "io.reactivex.rxjava2:rxjava:$libs.rxJavaVersion" } // <networking-lib> build.gradle dependencies { ... def libs = rootProject.ext.libraries implementation "org.jetbrains.kotlin:...:$libs.kotlinVersion" implementation "io.reactivex.rxjava2:...:$libs.rxJavaVersion" }
  18. • Managing/updating versions of dependencies is now easier - just

    need to change in one place • Still has the problem of duplication of dependencies
  19. #1

  20. #1 • Fairly complex projects • Multiple modules • You

    will find a lot of repetitions in the dependencies
  21. #1 // <login> build.gradle dependencies { implementation fileTree(dir: 'libs', include:

    ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies }
  22. #1 // <login> build.gradle dependencies { implementation fileTree(dir: 'libs', include:

    ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // <profile> build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies }
  23. #1 // <login> build.gradle dependencies { implementation fileTree(dir: 'libs', include:

    ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // <profile> build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // <search> build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies }
  24. #1 // <login> build.gradle dependencies { implementation fileTree(dir: 'libs', include:

    ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // <profile> build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // <search> build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // <core> build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies }
  25. #1 // <login> build.gradle dependencies { implementation fileTree(dir: 'libs', include:

    ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // <profile> build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // <search> build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } // <core> build.gradle dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" testImplementation "junit:junit:$libs.jUnitVersion" ... // other dependencies } Problem: Repeated declarations of dependencies in so many modules
  26. #1 Solution: extract common/shared dependencies and apply to the modules

  27. 1. Extract common dependencies // shared-dependencies.gradle - contains all shared

    dependncies dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion" ... testImplementation 'junit:junit:4.12' }
  28. 1. Extract common dependencies 2. Apply common dependencies to respective

    modules // <login> build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies }
  29. 1. Extract common dependencies 2. Apply common dependencies to respective

    modules // <login> build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // <profile> build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies }
  30. 1. Extract common dependencies 2. Apply common dependencies to respective

    modules // <login> build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // <profile> build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // <search> build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies }
  31. 1. Extract common dependencies 2. Apply common dependencies to respective

    modules // <login> build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // <profile> build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // <search> build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies } // <core> build.gradle apply from: “relative/path/to/shared-dependencies.gradle" ... dependencies { ... // other dependencies }
  32. • Managing shared dependencies becomes easier • Eliminates repeated declaration

    of dependencies
  33. #2

  34. #2 • Fairly complex projects • Multiple modules • You

    will find a lot of repetitions in the configurations of the modules
  35. #2

  36. #2 // <login> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion

    defaultConfig {...} buildTypes {...} }
  37. #2 // <login> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion

    defaultConfig { minSdkVersion sdk.minSdkVersion targetSdkVersion sdk.targetSdkVersion versionCode 198828 versionName "1.5.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles 'consumer-rules.pro' ... } buildTypes {...} }
  38. #2 // <login> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion

    defaultConfig {...} buildTypes { debug { minifyEnabled ... proguardFiles ... } release { minifyEnabled ... proguardFiles ... } } }
  39. #2 // <login> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion

    defaultConfig {...} buildTypes {...} }
  40. #2 // <login> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion

    defaultConfig {...} buildTypes {...} } // <profile> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} }
  41. #2 // <login> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion

    defaultConfig {...} buildTypes {...} } // <profile> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} } // <search> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} }
  42. #2 // <login> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion

    defaultConfig {...} buildTypes {...} } // <profile> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} } // <search> build.gradle android { compileSdkVersion sdk.compileSdkVersion buildToolsVersion sdk.buildToolsVersion defaultConfig {...} buildTypes {...} } Problem: Repeated configuration in so many modules
  43. 1. Extract common configuration into separate file https://handstandsam.com/2019/03/12/sharing-gradle-configuration-in-multi-module-android-projects/ // common-android-config.gradle

    apply plugin: 'kotlin-android' android { compileSdkVersion sdk.compileSdkVersion defaultConfig { minSdkVersion sdk.minSdkVersion targetSdkVersion sdk.targetSdkVersion versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } } Further reading:
  44. 1. Extract common configuration into separate file https://handstandsam.com/2019/03/12/sharing-gradle-configuration-in-multi-module-android-projects/ Further reading:

    2. Apply config to android modules // <login> build.gradle apply from: "$rootProject.projectDir/common-android-config.gradle" ...
  45. • Eliminates repeated configuration of common build logic • Same

    applies to other common configuration you may have across multiple modules. https://handstandsam.com/2019/03/12/sharing-gradle-configuration-in-multi-module-android-projects/ Further reading:
  46. Taking it even further with Kotlin DSL

  47. Why Kotlin DSL? • Kotlin is now really popular •

    Same language for code & build logic
  48. Why Kotlin DSL? • Kotlin is now really popular •

    Same language for code & build logic • Better IDE support for build scripts in Kotlin. • Jump to declaration, syntax highlighting, etc
  49. Kotlin DSL prerequisites • Gradle 5.0 • Java 8

  50. Tips for migrating to Kotlin DSL

  51. Tips for migrating to Kotlin DSL 1. <file.gradle> becomes <file.gradle.kts>

    2. Single quotes become double quotes 3. Property assignments should have assignment operator ‘=‘ 4. Function calls should have parenthes
  52. buildSrc • Gradle allows us create a module to add

    complex build related logic - like plugins, custom tasks, etc.
  53. buildSrc • Gradle allows us create a module to add

    complex build related logic - like plugins, custom tasks, etc. • It’s a regular module with it’s own: • build.gradle.kts • src/main/java or src/main/kotlin
  54. Adding dependencies versions to buildSrc Anatomy of the buildSrc module

    for dependencies versioning
  55. dependencies.gradle -> dependencies.kt // build.gradle.kts plugins { `kotlin-dsl` } repositories

    { jcenter() }
  56. dependencies.gradle -> dependencies.kt // Dependencies.kt object SdkVersions { const val

    compileSdkVersion = 28 const val minSdkVersion = 21 const val targetSdkVersion = 28 } object Deps { const val kotlinStdLib = “org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41" const val gson = “com.google.code.gson:gson:2.8.5" ... object Rx { const val rxJava2 = "io.reactivex.rxjava2:rxjava:2.2.10" const val rxAndroid = "io.reactivex.rxjava2:rxandroid:2.1.1" } ... }
  57. dependencies.gradle -> dependencies.kt // Dependencies.kt object SdkVersions { const val

    compileSdkVersion = 28 const val minSdkVersion = 21 const val targetSdkVersion = 28 } object Deps { const val kotlinStdLib = “org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41" const val gson = “com.google.code.gson:gson:2.8.5" ... object Rx { const val rxJava2 = "io.reactivex.rxjava2:rxjava:2.2.10" const val rxAndroid = "io.reactivex.rxjava2:rxandroid:2.1.1" } ... }
  58. dependencies.gradle -> dependencies.kt // Dependencies.kt object Deps { const val

    kotlinStdLib = “org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41" const val gson = “com.google.code.gson:gson:2.8.5" } // Usage in build.gradle dependencies { implementation Deps.kotlinStdLib implementation Deps.gson ... }
  59. dependencies.gradle -> dependencies.kt // Dependencies.kt object Deps { const val

    kotlinStdLib = “org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41" const val gson = “com.google.code.gson:gson:2.8.5" } // Usage in build.gradle dependencies { implementation Deps.kotlinStdLib implementation Deps.gson ... } Syntax highlighting ✅ “Jump to declaration” ✅
  60. Migrating an Android project

  61. // settings.gradle include ':app', ':data', ':domain'

  62. // settings.gradle include ':app', ':data', ':domain' // settings.gradle.kts include(":app", ":data",

    ":domain")
  63. // settings.gradle include ':app', ':data', ':domain' // settings.gradle.kts include(":app", ":data",

    ":domain") ’:app’ becomes “:app” include becomes include()
  64. // app-level build.gradle

  65. // app-level build.gradle apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android

    { compileSdkVersion 28 defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion 21 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }
  66. // app-level build.gradle.kts apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android

    { compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode = 1 versionName = "1.0" } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro') } } } dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31") implementation("androidx.appcompat:appcompat:1.0.2") }
  67. What changed? apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android {

    compileSdkVersion 28 defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion 21 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }
  68. What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android {

    compileSdkVersion 28 defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion 21 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }
  69. What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android {

    compileSdkVersion 28 defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion 21 targetSdkVersion 28 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }
  70. What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android {

    compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }
  71. What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android {

    compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled true proguardFiles ... } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }
  72. What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android {

    compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode 1 versionName "1.0" } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile(‘...’), 'proguard-rules.pro') } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }
  73. What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android {

    compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode 1 versionName "1.0" } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile(‘...’), 'proguard-rules.pro') } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31" implementation "androidx.appcompat:appcompat:1.0.2" }
  74. What changed? apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android {

    compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode 1 versionName "1.0" } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile(‘...’), 'proguard-rules.pro') } } } dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31") implementation("androidx.appcompat:appcompat:1.0.2") }
  75. // app-level build.gradle.kts apply(plugin = "com.android.application") apply(plugin = "kotlin-android") android

    { compileSdkVersion(28) defaultConfig { applicationId "com.segunfamisa.kotlindsl" minSdkVersion(21) targetSdkVersion(28) versionCode = 1 versionName = "1.0" } buildTypes { getByName("release") { isMinifyEnabled = true proguardFiles(getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro') } } } dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.31") implementation("androidx.appcompat:appcompat:1.0.2") }
  76. // top-level build.gradle

  77. // top-level build.gradle buildscript { ext.kotlin_version = '1.3.31' repositories {

    google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() jcenter() } }
  78. // top-level build.gradle.kts buildscript { extra.apply { set("kotlin_version", "1.3.31") }

    repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:3.4.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${extras.get("kotlin_version")}) } } allprojects { repositories { google() jcenter() } }
  79. What changed?

  80. // top-level build.gradle buildscript { ext.kotlin_version = '1.3.31' repositories {

    google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() jcenter() } } What changed?
  81. What changed? // top-level build.gradle.kts buildscript { extra.apply { set("kotlin_version",

    "1.3.31") } repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:3.4.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${extras.get("kotlin_version")}) } } allprojects { repositories { google() jcenter() } }
  82. // top-level build.gradle buildscript { extra.apply { set("kotlin_version", "1.3.31") }

    repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } allprojects { repositories { google() jcenter() } } What changed?
  83. // top-level build.gradle.kts buildscript { extra.apply { set("kotlin_version", "1.3.31") }

    repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:3.4.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${extras.get("kotlin_version")}) } } allprojects { repositories { google() jcenter() } } What changed?
  84. // top-level build.gradle.kts buildscript { extra.apply { set("kotlin_version", "1.3.31") }

    repositories { google() jcenter() } dependencies { classpath("com.android.tools.build:gradle:3.4.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${extras.get("kotlin_version")}) } } allprojects { repositories { google() jcenter() } }
  85. Current pain points with Kotlin DSL

  86. Current pain points with Kotlin DSL • IDE support is

    not yet at
  87. Current pain points with Kotlin DSL • IDE support is

    not yet at • Additional configuration time in your build process
  88. Final words

  89. Final words • Keep it DRY (Don’t Repeat Yourself) -

    rule of three applies here
  90. Final words • Keep it DRY (Don’t Repeat Yourself) -

    rule of three applies here • Modular code rocks
  91. Final words • Keep it DRY (Don’t Repeat Yourself) -

    rule of three applies here • Modular code rocks • Take advantage of IDE support with Kotlin DSL
  92. Resources https://handstandsam.com/2019/03/12/sharing-gradle-configuration-in-multi-module-android-projects/ https://segunfamisa.com/posts/android-gradle-extra-properties https://gradle.com/blog/getting-started-with-gradle-kotlin-dsl/ https://github.com/gradle/kotlin-dsl https://blog.codinghorror.com/rule-of-three/

  93. Thanks! Segun Famisa, Android GDE