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

Modularizing Android Applications

Mauin
October 26, 2017

Modularizing Android Applications

droidcon London 2017
droidcon Italy 2018

The recording of the talk at droidcon London is available here: http://uk.droidcon.com/skillscasts/10525-modularizing-android-applications#video

Most Android applications consist of one big, monolithic application project. As your application grows this single project can become harder and harder to manage, responsibilities become unclear and build times grow. Marvin will share how you can split up such an Android application into multiple, smaller modules. We will discuss how doing so might change the way you work in your applications codebase and how it can help in setting up clearer interfaces and responsibilities across teams. As modularizing an application changes the way you interact with the build system we will talk about how your build setup and times might change and how different build systems (such as Gradle, Buck and Bazel) interact with multiple modules.

Mauin

October 26, 2017
Tweet

More Decks by Mauin

Other Decks in Programming

Transcript

  1. . !"" app # !"" build.gradle # $"" src #

    $"" main # !"" AndroidManifest.xml # !"" kotlin # # $"" com.some.app # # !"" Application.kt # # !"" login # # # !"" LoginActivity.kt # # # !"" LoginPresenter.kt # # # !"" LoginRepository.kt # # !"" content # # # !"" ContentActivity.kt # # # !"" ContentFragment.kt # # # !"" ContentDatabase.kt # # # !"" ApiClient.kt # # !"" feature3 # # !"" feature4 # # !"" apiclient # # !"" ... # # !"" ... # $"" res # !"" drawable # $"" ... # !"" build.gradle !"" gradle $"" settings.gradle
  2. . !"" app # !"" build.gradle # $"" src #

    $"" main # !"" AndroidManifest.xml # !"" kotlin # # $"" com.some.app # # !"" Application.kt # # !"" login # # # !"" LoginActivity.kt # # # !"" LoginPresenter.kt # # # !"" LoginRepository.kt # # !"" content # # # !"" ContentActivity.kt # # # !"" ContentFragment.kt # # # !"" ContentDatabase.kt # # # !"" ApiClient.kt # # !"" feature3 # # !"" feature4 # # !"" apiclient # # !"" ... # # !"" ... # $"" res # !"" drawable # $"" ... # !"" build.gradle !"" gradle $"" settings.gradle
  3. . !"" app # !"" build.gradle # $"" src #

    $"" main # !"" AndroidManifest.xml # !"" kotlin # # $"" com.some.app # # !"" Application.kt # # !"" login # # # !"" LoginActivity.kt # # # !"" LoginPresenter.kt # # # !"" LoginRepository.kt # # !"" content # # # !"" ContentActivity.kt # # # !"" ContentFragment.kt # # # !"" ContentDatabase.kt # # # !"" ApiClient.kt # # !"" feature3 # # !"" feature4 # # !"" apiclient # # !"" ... # # !"" ... # $"" res # !"" drawable # $"" ... # !"" build.gradle !"" gradle $"" settings.gradle
  4. . !"" app # !"" build.gradle # $"" src #

    $"" main # !"" AndroidManifest.xml # !"" kotlin # # $"" com.some.app # # !"" Application.kt # # !"" login # # # !"" LoginActivity.kt # # # !"" LoginPresenter.kt # # # !"" LoginRepository.kt # # !"" content # # # !"" ContentActivity.kt # # # !"" ContentFragment.kt # # # !"" ContentDatabase.kt # # # !"" ApiClient.kt # # !"" feature3 # # !"" feature4 # # !"" apiclient # # !"" ... # # !"" ... # $"" res # !"" drawable # $"" ... # !"" build.gradle !"" gradle $"" settings.gradle
  5. . !"" app # !"" build.gradle # $"" src #

    $"" main # !"" AndroidManifest.xml # !"" kotlin # # $"" com.some.app # # !"" Application.kt # # !"" login # # # !"" LoginActivity.kt # # # !"" LoginPresenter.kt # # # !"" AccountRepository.kt # # !"" content # # !"" apiclient # $"" res # !"" drawable # $"" … !"" build.gradle !"" gradle $"" settings.gradle
  6. . !"" app # !"" build.gradle # $"" src #

    $"" main # !"" AndroidManifest.xml # !"" kotlin # # $"" com.some.app # # !"" Application.kt # # !"" login # # # !"" LoginActivity.kt # # # !"" LoginPresenter.kt # # # !"" AccountRepository.kt # # !"" content # # !"" apiclient # $"" res # !"" drawable # $"" … !"" build.gradle !"" gradle $"" settings.gradle
  7. . !"" app # !"" build.gradle # $"" src #

    $"" main # !"" AndroidManifest.xml # !"" kotlin # # $"" com.some.app # # !"" Application.kt # # !"" login # # # !"" LoginActivity.kt # # # !"" LoginPresenter.kt # # # !"" AccountRepository.kt # # !"" content # $"" res # !"" drawable # $"" … !"" apiclient # !"" build.gradle # $"" src !"" build.gradle !"" gradle $"" settings.gradle
  8. . !"" app # !"" build.gradle # $"" src #

    $"" main # !"" AndroidManifest.xml # !"" kotlin # # $"" com.some.app # # !"" Application.kt # # !"" login # # # !"" LoginActivity.kt # # # !"" LoginPresenter.kt # # # !"" AccountRepository.kt # # !"" content # $"" res # !"" drawable # $"" … !"" apiclient # !"" build.gradle # $"" src !"" build.gradle !"" gradle $"" settings.gradle settings.gradle
  9. . !"" app # !"" build.gradle # $"" src #

    $"" main # !"" AndroidManifest.xml # !"" kotlin # # $"" com.some.app # # !"" Application.kt # # !"" login # # # !"" LoginActivity.kt # # # !"" LoginPresenter.kt # # # !"" AccountRepository.kt # # !"" content # $"" res # !"" drawable # $"" … !"" apiclient # !"" build.gradle # $"" src !"" build.gradle !"" gradle $"" settings.gradle settings.gradle include ‘:app’, ‘:apiclient’
  10. . !"" app # !"" build.gradle # $"" src #

    $"" main # !"" AndroidManifest.xml # !"" kotlin # # $"" com.some.app # # !"" Application.kt # # !"" login # # # !"" LoginActivity.kt # # # !"" LoginPresenter.kt # # # !"" AccountRepository.kt # # !"" content # $"" res # !"" drawable # $"" … !"" modules # $"" apiclient # !"" build.gradle # $"" src !"" build.gradle !"" gradle $"" settings.gradle settings.gradle include ‘:app’, ‘:modules:apiclient’
  11. :app :apiclient apply plugin: ‘kotlin’ apply plugin: ‘com.android.application’ implementation project(':apiclient')

    :login apply plugin: ‘com.android.library’ implementation project(‘:login') content
  12. :app :apiclient apply plugin: ‘kotlin’ apply plugin: ‘com.android.application’ implementation project(':apiclient')

    :login apply plugin: ‘com.android.library’ implementation project(‘:login') implementation project(‘:apiclient’) content
  13. :app :apiclient apply plugin: ‘kotlin’ apply plugin: ‘com.android.application’ implementation project(':apiclient')

    :login apply plugin: ‘com.android.library’ implementation project(‘:login') implementation project(‘:apiclient’) content
  14. :app :apiclient apply plugin: ‘kotlin’ apply plugin: ‘com.android.application’ implementation project(':apiclient')

    :login apply plugin: ‘com.android.library’ implementation project(‘:login') implementation project(‘:apiclient’) content :user
  15. :app :apiclient apply plugin: ‘kotlin’ apply plugin: ‘com.android.application’ implementation project(':apiclient')

    :login apply plugin: ‘com.android.library’ implementation project(‘:login') implementation project(‘:apiclient’) content :user
  16. :app :apiclient apply plugin: ‘kotlin’ apply plugin: ‘com.android.application’ implementation project(':apiclient')

    :login apply plugin: ‘com.android.library’ implementation project(‘:login') implementation project(‘:apiclient’) content :user :utils
  17. :app :apiclient apply plugin: ‘kotlin’ apply plugin: ‘com.android.application’ implementation project(':apiclient')

    :login apply plugin: ‘com.android.library’ implementation project(‘:login') implementation project(‘:apiclient’) content :user :utils
  18. :app :apiclient apply plugin: ‘kotlin’ apply plugin: ‘com.android.application’ implementation project(':apiclient')

    :login apply plugin: ‘com.android.library’ implementation project(‘:login') implementation project(‘:apiclient’) content :user :utils :rabbithole
  19. :app :apiclient apply plugin: ‘kotlin’ apply plugin: ‘com.android.application’ implementation project(':apiclient')

    :login apply plugin: ‘com.android.library’ implementation project(‘:login') implementation project(‘:apiclient’) content :user :utils :rabbithole
  20. :app :apiclient apply plugin: ‘kotlin’ apply plugin: ‘com.android.application’ implementation project(':apiclient')

    :login apply plugin: ‘com.android.library’ implementation project(‘:login') implementation project(‘:apiclient’) content :user :utils :rabbithole
  21. :base content apiclient apply plugin: ‘com.android.library’ :app apply plugin: ‘com.android.application’

    :login implementation project(‘:base') apply plugin: ‘com.android.library’ implementation project(‘:base') implementation project(‘:login’)
  22. :base content apply plugin: ‘com.android.library’ :app apply plugin: ‘com.android.application’ :login

    implementation project(‘:base') :apiclient apply plugin: ‘com.android.library’ apply plugin: ‘kotlin’ implementation project(‘:base') implementation project(‘:login’)
  23. :base apply plugin: ‘com.android.library’ :app :login apply plugin: ‘com.android.library’ :content

    apply plugin: ‘com.android.library’ apply plugin: ‘com.android.application’
  24. :base apply plugin: ‘com.android.library’ :app :login apply plugin: ‘com.android.library’ :content

    apply plugin: ‘com.android.library’ :androidwear :instantapp :sample
  25. Each module has a clear API Clear responsibilities between teams

    Module maintenance goes up Compile times go down
  26. Define your dependencies in one place dependencies.gradle file Assure dependency

    versions are the same across all modules Define core dependencies in a base module
  27. // dependencies.gradle ext { androidBuildToolsVersion = '26.0.1' androidCompileSdkVersion = 26

    androidMinSdkVersion = 23 androidTargetSdkVersion = 26 libraries = [ rxJava2 : "io.reactivex.rxjava2:rxjava:2.1.5", ... ] }
  28. // dependencies.gradle ext { androidBuildToolsVersion = '26.0.1' androidCompileSdkVersion = 26

    androidMinSdkVersion = 23 androidTargetSdkVersion = 26 libraries = [ rxJava2 : "io.reactivex.rxjava2:rxjava:2.1.5", ... ] } // build.gradle android { compileSdkVersion androidCompileSdkVersion buildToolsVersion androidBuildToolsVersion ... } dependencies { implementation libraries.rxJava2 }
  29. apply plugin: “com.android.library” android { compileSdkVersion versions.compileSdk defaultConfig { minSdkVersion

    versions.minSdk targetSdkVersion versions.targetSdk versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
  30. apply plugin: “com.android.library” android { compileSdkVersion versions.compileSdk defaultConfig { minSdkVersion

    versions.minSdk targetSdkVersion versions.targetSdk versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } my-base-library.gradle:
  31. @Component(modules = { ApplicationModule.class, ApiClientModule.class // <- comes from the

    :apiclient module }) public interface ApplicationComponent { }
  32. :base apply plugin: ‘com.android.library’ :app apply plugin: ‘com.android.application’ :login apply

    plugin: ‘com.android.library’ :content apply plugin: ‘com.android.library’
  33. :base apply plugin: ‘com.android.library’ :app apply plugin: ‘com.android.application’ :login apply

    plugin: ‘com.android.library’ :content apply plugin: ‘com.android.library’ ?
  34. Start writing new components in separate modules Identify core modules

    Make a plan and extract slowly Enjoy the multi-module world