Android Studio 利用Gradle组织更清晰的打包脚本

前言

我们最初写gradle脚本时候,通常的做法是把所有的打包脚本都写在了build.gradle文件中,这样做的容易引发的问题:

  1. 项目中多个模块的build.gradle配置的依赖版本重复或compileSdkVersion等不统一;
  2. 会导致一些依赖重复导致冲突;
  3. Android Support Library版本问题引发的一些列问题;
  4. 影响 build.gradle 文件扩展性、可读性、以及难以维护等;

针对以上问题,去寻找一个更清晰的打包系统,帮助开发者在组织打包脚本变得更简洁清晰。


方式一

抽取统一的依赖
在根目录新建一个config.gradle文件,里面键入要统一的依赖:

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'
        
    ]
}

然后在根目录的build.gradle文件里面头部新增一句引用apply from: "config.gradle"

在module里面开始应用:

compileSdkVersion rootProject.ext.android.compileSdkVersion //android{}节点

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

clean一下去External Libraries看看,是不是还有重复的,如果还有,说明前面config里面的依赖其他地方还有遗漏的,全局搜索一下在同样方式替换一下就好了。


方式二(更优方式)

此方式参照开源架构Android-CleanArchitecture中的打包组织架构。根据功能的不同,将打包系统分为多个脚本文件。
打包系统的组织结构如下:

Android Studio 利用Gradle组织更清晰的打包脚本
image.png

ci.gradle文件如下:

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,里面键入要统一的依赖

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}",
    ]
}

项目 project 目录下 build.gradle 中开头加入

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

模块 module 目录下的 build.gradle

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
}
上一篇:万网域名阿里云计算产业链上的关键一环


下一篇:Android获取手机应用