Android Studio uses Gradle to organize clearer packaging scripts

Keywords: Android Gradle Google Junit

Preface

When we first wrote gradle scripts, we usually wrote all the packaged scripts in the build.gradle file, which is easy to cause problems.

  1. Dependent version duplication of build.gradle configuration or inconsistency of compileSdkVersion of multiple modules in the project;
  2. It will lead to some dependency duplication and conflict.
  3. Some column problems caused by Android Support Library version problems;
  4. It affects the extensibility, readability and maintenance of build.gradle files.

To solve these problems, find a clearer packaging system to help developers organize packaging scripts more concise and clear.

One way

Extract Unified Dependency
Create a new config.gradle file in the root directory, and type the dependencies you want to unify:

ext {
    android = [
        compileSdkVersion: 23,
        buildToolsVersion: "23.0.3",
        minSdkVersion    : 15,
        targetSdkVersion : 22,
        versionCode      : 1,
        versionName      : "1.0"
    ]

    dependencies = [
        "gson"               : "com.google.code.gson:gson:2.6.2",
        "eventbus"           : 'org.greenrobot:eventbus:3.0.0',
        "butterknife"        : 'com.jakewharton:butterknife:7.0.1',
        "support-design"     : 'com.android.support:design:24.1.1',
        "support-appcompatV7": 'com.android.support:appcompat-v7:24.1.1',
        "support-percent"    : 'com.android.support:percent:24.1.1',
        "support-multidex"   : 'com.android.support:multidex:1.0.1',
        "glide"              : 'com.github.bumptech.glide:glide:3.7.0',
        "support-v4"         : 'com.android.support:support-v4:24.1.1',
        "okhttp3"            : 'com.squareup.okhttp3:okhttp:3.3.1',
        "nineoldandroids"    : 'com.nineoldandroids:library:2.4.0'
        
    ]
}

Then add a new quotation from apply: "config. gradle" in the header of the build.gradle file in the root directory

Start applying in module:

compileSdkVersion rootProject.ext.android.compileSdkVersion //android {} node

compile rootProject.ext.dependencies["support-appcompatV7"] //dependencies {} node

Go to External Libraries to see if there is any duplication. If there is one, it means that the dependencies in the previous config are still missing from other places. It would be better to replace them in the same way by global search.

Mode 2 (Better Way)

This approach refers to the Packaging Organization Architecture in the open source architecture Android-Clean Architecture. According to the different functions, the packaging system is divided into several script files.
The organizational structure of the packaging system is as follows:

image.png

The ci.gradle file is as follows:

def ciServer = 'TRAVIS'
def executingOnCI = "true".equals(System.getenv(ciServer))

// Since for CI we always do full clean builds, we don't want to pre-dex
// See http://tools.android.com/tech-docs/new-build-system/tips
subprojects {
    project.plugins.whenPluginAdded { plugin ->
        if ('com.android.build.gradle.AppPlugin'.equals(plugin.class.name) || 'com.android.build.gradle.LibraryPlugin'.equals(plugin.class.name)) {
            project.android.dexOptions.preDexLibraries = !executingOnCI
        }
    }
}

dependencies.gradle, where you type the dependencies you want to unify

allprojects {
    repositories {
        jcenter()
    }
}

ext {
    //Android
    androidBuildToolsVersion = "24.0.1"
    androidMinSdkVersion = 15
    androidTargetSdkVersion = 21
    androidCompileSdkVersion = 21

    //Libraries
    daggerVersion = '2.8'
    butterKnifeVersion = '7.0.1'
    recyclerViewVersion = '21.0.3'
    rxJavaVersion = '2.0.2'
    rxAndroidVersion = '2.0.1'
    javaxAnnotationVersion = '1.0'
    javaxInjectVersion = '1'
    gsonVersion = '2.3'
    okHttpVersion = '2.5.0'
    androidAnnotationsVersion = '21.0.3'
    arrowVersion = '1.0.0'

    //Testing
    robolectricVersion = '3.1.1'
    jUnitVersion = '4.12'
    assertJVersion = '1.7.1'
    mockitoVersion = '1.9.5'
    dexmakerVersion = '1.0'
    espressoVersion = '2.0'
    testingSupportLibVersion = '0.1'

    //Development
    leakCanaryVersion = '1.3.1'

    presentationDependencies = [
        daggerCompiler:     "com.google.dagger:dagger-compiler:${daggerVersion}",
        dagger:             "com.google.dagger:dagger:${daggerVersion}",
        butterKnife:        "com.jakewharton:butterknife:${butterKnifeVersion}",
        recyclerView:       "com.android.support:recyclerview-v7:${recyclerViewVersion}",
        rxJava:             "io.reactivex.rxjava2:rxjava:${rxJavaVersion}",
        rxAndroid:          "io.reactivex.rxjava2:rxandroid:${rxAndroidVersion}",
        javaxAnnotation:    "javax.annotation:jsr250-api:${javaxAnnotationVersion}"
    ]

    presentationTestDependencies = [
        mockito:            "org.mockito:mockito-core:${mockitoVersion}",
        dexmaker:           "com.google.dexmaker:dexmaker:${dexmakerVersion}",
        dexmakerMockito:    "com.google.dexmaker:dexmaker-mockito:${dexmakerVersion}",
        espresso:           "com.android.support.test.espresso:espresso-core:${espressoVersion}",
        testingSupportLib:  "com.android.support.test:testing-support-lib:${testingSupportLibVersion}",
    ]

    domainDependencies = [
        javaxAnnotation:    "javax.annotation:jsr250-api:${javaxAnnotationVersion}",
        javaxInject:        "javax.inject:javax.inject:${javaxInjectVersion}",
        rxJava:             "io.reactivex.rxjava2:rxjava:${rxJavaVersion}",
        arrow:              "com.fernandocejas:arrow:${arrowVersion}"
    ]

    domainTestDependencies = [
        junit:              "junit:junit:${jUnitVersion}",
        mockito:            "org.mockito:mockito-core:${mockitoVersion}",
        assertj:            "org.assertj:assertj-core:${assertJVersion}"
    ]

    dataDependencies = [
        daggerCompiler:     "com.google.dagger:dagger-compiler:${daggerVersion}",
        dagger:             "com.google.dagger:dagger:${daggerVersion}",
        okHttp:             "com.squareup.okhttp:okhttp:${okHttpVersion}",
        gson:               "com.google.code.gson:gson:${gsonVersion}",
        rxJava:             "io.reactivex.rxjava2:rxjava:${rxJavaVersion}",
        rxAndroid:          "io.reactivex.rxjava2:rxandroid:${rxAndroidVersion}",
        javaxAnnotation:    "javax.annotation:jsr250-api:${javaxAnnotationVersion}",
        javaxInject:        "javax.inject:javax.inject:${javaxInjectVersion}",
        androidAnnotations: "com.android.support:support-annotations:${androidAnnotationsVersion}"
    ]

    dataTestDependencies = [
        junit:              "junit:junit:${jUnitVersion}",
        assertj:            "org.assertj:assertj-core:${assertJVersion}",
        mockito:            "org.mockito:mockito-core:${mockitoVersion}",
        robolectric:        "org.robolectric:robolectric:${robolectricVersion}",
    ]

    developmentDependencies = [
        leakCanary: "com.squareup.leakcanary:leakcanary-android:${leakCanaryVersion}",
    ]
}

Start with build.gradle in the project project directory

apply from: 'buildsystem/ci.gradle'
apply from: 'buildsystem/dependencies.gradle'
...

build.gradle in the module module directory

apply plugin: 'com.android.library'
android {
    def globalConfiguration = rootProject.extensions.getByName("ext")
    compileSdkVersion globalConfiguration.getAt("androidCompileSdkVersion")
    buildToolsVersion globalConfiguration.getAt("androidBuildToolsVersion")

    defaultConfig {
        minSdkVersion globalConfiguration.getAt("androidMinSdkVersion")
        targetSdkVersion globalConfiguration.getAt("androidTargetSdkVersion")
        versionCode globalConfiguration.getAt("androidVersionCode")
    }
    ...
}

dependencies {
    def domainDependencies = rootProject.ext.domainDependencies
    def domainTestDependencies = rootProject.ext.domainTestDependencies

    provided domainDependencies.daggerCompiler
    provided domainDependencies.javaxAnnotation

    compile domainDependencies.dagger
    compile domainDependencies.rxJava

    testCompile domainTestDependencies.junit
    testCompile domainTestDependencies.mockito
}

Posted by franklyn on Sun, 03 Feb 2019 01:45:15 -0800