[AS3.0.1]Gradle代码整合优化

1.build.gradle讲解

首先我将一个demo项目中的一份build.gradle拿出来讲解下

apply plugin: 'com.android.application'
apply plugin: 'com.jakewharton.butterknife'

android {
    //签名配置
    signingConfigs {
        //签名Name
        config {
            //签名别名
            keyAlias 'gjn'
            //签名别名密码
            keyPassword '11223344'
            //签名文件位置
            storeFile file('D:/project/MyDemo/gjnKey.jks')
            //签名密码
            storePassword '11223344'
        }
    }
    //开发环境版本号
    compileSdkVersion 26
    //默认配置
    defaultConfig {
        //Id
        applicationId "com.gjn.mydemo"
        //最小支持版本号
        minSdkVersion 19
        //运行版本号
        targetSdkVersion 25
        //appCode
        versionCode 1
        //app版本号
        versionName "1.0"
        //测试相关
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    //Build类型 默认有release和debug两个版本
    buildTypes {
        release {
            //是否开始混淆
            minifyEnabled false
            //混淆文件路径
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //打包时候调用的签名
            signingConfig signingConfigs.config
            //在BuildConfig生成一个String类型的Host=release_Host
            //即 public static final String Host = "release_Host";
            buildConfigField "String", "Host", "\"release_Host\""
            //编译之后会在res文件中的string.xml中加入一个string类型的app_name1=myMode
            //即 myMode
            resValue "string", "app_name1", "myMode"
            //修改build之后的app名称
            //这边编译出来的名字是 release_1.0.apk
            //这个写法是Android Studio 3.0之后的方法
            android.applicationVariants.all { variant ->
                variant.outputs.all {
                    outputFileName = "${variant.name}_${variant.versionName}.apk"
                }
            }
        }
        debug {
            //为Id添加后缀 这边生成新的Id为com.gjn.mydemo.debug
            applicationIdSuffix ".debug"
            //这边下面和上面是一样

            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            buildConfigField("String", "Host", "\"debug_Host\"")
            resValue("string", "app_name1", "myModedebug")

            //占位符 替换AndroidManifest.xml 中的${test_key}字符
            //AndroidManifest.xml中的源代码为
            //
            //替换之后
            //
            manifestPlaceholders = ["test_key": "debug_key"]
        }
    }
    //多版本
    productFlavors{
        //dev版本
        dev{
            manifestPlaceholders = ["test_key": "release_key"]
        }
        //free版本
        free{
            //这边在提下,由于free也会有release和debug两个版本
            //release的Id为com.gjn.mydemo.free
            //debug的Id为com.gjn.mydemo.free.debug
            applicationIdSuffix ".free"
            manifestPlaceholders = ["test_key": "free_key"]
        }
    }
    //遍历了全部版本
    productFlavors.all{
        //设置统一Code Android Studio 3.0之后需要设置这个属性 不然构建多版本的时候会报错
        flavorDimensions("versionCode")
    }
}
//导入第三方之类的jar aar 等 就不说了
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support:design:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    implementation 'com.jakewharton:butterknife:8.7.0'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0'
    implementation 'com.github.bumptech.glide:glide:3.7.0'
    implementation 'com.google.code.gson:gson:2.8.0'
    implementation 'com.squareup.okhttp3:okhttp:3.8.1'
    implementation 'io.reactivex.rxjava2:rxjava:2.1.1'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
}

我将大部分内容都设置了备注,可以看到很多常用的属性设置。还有许多其他的,后续在补充


2.Groovy讲解

这边我稍微对Groovy的语法和逻辑说一点!
首先说下
关于注释之类和java是一样的

  • 字符串

在java中就只有一种"android"

而Groovy中有
单行'android', "android"
多行 '''android''', """android""
还有/.../${...}

  • 集合(List,Map)

List

创建和初始化

def list = [1,'hello',false]

这边不需要List中的每个类型都相同,当然Map也一样。

使用

    println list[1]     //输出 hello
    println list[-1]    //输出 false
    list[1] = 5         //5 替换 hello
    list[0] = "android" //android 替换 1
    list << "gjn"       //追加 gjn
    list.each { l ->    //遍历整个list
        println l       //每次输出一项
    }

结果

hello
false
android
5
false
gjn

Map

创建和初始化

def map = [1:'hello',android:233,b:false]

使用

    println map[1]      //输出 hello
    println map.b       //输出 false
    map << [2:33]       //追加 2:33
    map.each { k,v->    //遍历map
        println k+":"+v
    }

结果

hello
false
1:hello
android:233
b:false
2:33
  • 数组

关于数组
groovy 其实没有严格区分数组和集合,数组的定义和使用方法跟集合一样,只是你需要强制声明为数组,否则默认为集合。

创建和初始化

String[] arrString = ['hello',"android","""groovy
=============="""]
def arrNum = [1,2,3] as int[]

直接String[]和Java一样是创建数组
as int[]是把arrNum设置为数组,不然就会变成集合

使用

    arrString.each {str->
        println str
    }
    arrNum.each {num->
        println num
    }

结果

hello
android
groovy
==============
1
2
3
  • 遍历
    groovy中的遍历有2个each{...}all{...}
    遍历在上面的数组和集合都使用了,大体上都知道使用了。
    拿第一个说下each就是Java中的foreach
    list.each { l ->    //遍历整个list
        println l       //每次输出一项
    }

其实就等于Java中的

    List list = new ArrayList<>();
    for(String l : list){
        System.out.println(l);
    }

all和each的使用是一样的,区别我查了下,有提到是each使用的是迭代,不能实时修改值,all使用的是拾取对象,可以修改值。好比ArrayList和CopyOnWriteArrayList的区别吧!
我也不太确定,只是在 Android Gradle 3.0.0-alpha2 plugin, Cannot set the value of read-only property 'outputFile'
中有看到。

  • 方法简化使用

groovy的一个特性
groovy 定义方法时可以不声明返回类型和参数类型,也可以不需要 return 语句,最后一行代码默认就是返回值。使用的时候也可以不需要添加括号。
使用1

def add(a,b){
    a+b
}

def str = add 1,2
println str    //结果为3

结果1

3

这边我们就能发现很多在build.gradle中的参数的真实代码
例如
compileSdkVersion 26 就是 compileSdkVersion(26)
applicationId "com.gjn.mydemo" 就是 applicationId("com.gjn.mydemo")
等等

使用2

def getmap(Map map){
    map.each {
        println it.key + ":" + it.value
    }
}

def map = [1:"hello",2:true]
getmap map

def map2 = [add:'groovy']
getmap map2

getmap add:'groovy test'

结果2

1:hello
2:true
add:groovy
add:groovy test

这次使用我们就发现了一个getmap add:'groovy test'和build.gradle中的apply plugin: 'com.android.application'很像有没有。
如果按照我们上面的写法,那么原本的apply方法就是

apply plugin: 'com.android.application'
等于
def map = [plugin: 'com.android.application']
apply(map)
  • 闭包

闭包是 groovy 的一大特性,例如build.gradle中的android{...}defaultConfig{...}buildTypes{...}dependencies{...}等 这些都是闭包的使用

使用

def add(a,Closure c){
    println a + c.call()
}

add(1,{2+3})
add 1,{
    5+6
}

结果

6
12

使用2

def myprintln(Closure c){
    println c.call()
}

myprintln {
    123
}
myprintln {
    "Msss"
}
myprintln {
    123+"Msss"
}

结果2

123
Msss
123Msss

Android Studio的build.gradle代码整合优化

继续来说关于build.gradle代码优化。这边我们拿最开始的build.gradle代码进行优化。
说是优化,其实就是吧一些东西写在另一个gradle文件下,然后直接调用就好了。而且把部分参数写在另一个gradle中,修改这些代码的时候,就根本不需要Sync build.gradle代码,也算加快了编译速度吧!

首先我们在项目的project目录下新建一个config.gradle文件
注:要让config.gradle代码能够在app的build.gradle中使用,在主项目的build.gradle中加入 apply from:'config.gradle' 表示导入config文件代码
具体位置如下

apply from:'config.gradle'
buildscript {
    repositories {
        ....
    }
    dependencies {
        ....
    }
}

allprojects {
    repositories {
        ....
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

创建好config.gradle文件之后写入一个ext{}
默认如下

ext{
    
}

然后我们看下,哪些可以写在config中
这边我选了签名相关APP的版本正式版和测试版之间相同的数据设置加载第三方库dependencies相关这几项
所以我在config中加入

ext{
    SigningConfigs = [
        
    ]
    DefaultConfig = [

    ]
    Release = [

    ]
    Debug = [

    ]
    Dependencies = [

    ]
}

之后我们对比原来的build.gradle进行配置config文件

ext{
    SigningConfigs = [
            keyAlias : 'gjn',
            keyPassword : '11223344',
            storeFile : 'D:/project/MyDemo/gjnKey.jks',
            storePassword : '11223344'
    ]
    DefaultConfig = [
            versionCode : 1,
            versionName : "1.0"
    ]
    Release = [
            "Host_bcf":"release_Host",
            "appname_res": "myMode",
            "test_key_mp": "release_key"
    ]
    Debug = [
            "Host_bcf":"debug_Host",
            "appname_res": "myModedebug",
            "test_key_mp": "debug_key"
    ]
    Dependencies = [
            appcompat:'com.android.support:appcompat-v7:26.1.0',
            design:'com.android.support:design:26.1.0',
            constraint:'com.android.support.constraint:constraint-layout:1.0.2',
            butterknife:'com.jakewharton:butterknife:8.7.0',
            glide:'com.github.bumptech.glide:glide:3.7.0',
            gson:'com.google.code.gson:gson:2.8.0',
            okhttp:'com.squareup.okhttp3:okhttp:3.8.1',
            rxjava:'io.reactivex.rxjava2:rxjava:2.1.1',
            rxandroid:'io.reactivex.rxjava2:rxandroid:2.0.1',
            retrofit:'com.squareup.retrofit2:retrofit:2.3.0',
            adapterrxjava2:'com.squareup.retrofit2:adapter-rxjava2:2.3.0',
            convertergson:'com.squareup.retrofit2:converter-gson:2.3.0',
    ]
}

现在看下如何在build.gradle中使用
首先先创建好对应的def

def sc = rootProject.ext.SigningConfigs
def dc = rootProject.ext.DefaultConfig
def r = rootProject.ext.Release
def d = rootProject.ext.Debug
def dep = rootProject.ext.Dependencies

之后就只要在用到的地方把原来的参数替换掉就好了
好比

    //签名配置
    signingConfigs {
        //签名Name
        config {
            //签名别名
            keyAlias 'gjn'
            //签名别名密码
            keyPassword '11223344'
            //签名文件位置
            storeFile file('D:/project/MyDemo/gjnKey.jks')
            //签名密码
            storePassword '11223344'
        }
    }

就变成了

    //签名配置
    signingConfigs {
        //签名Name
        config {
            //签名别名
            keyAlias sc.keyAlias
            //签名别名密码
            keyPassword sc.keyPassword
            //签名文件位置
            storeFile file(sc.storeFile)
            //签名密码
            storePassword sc.storePassword
        }
    }

使用是很简单的,这边要提及下第三方库导入相关,这边可以用上面学的groovy循环直接一次性全部加进去。可以省略很多代码。
直接改成

dep.each{ k,v->
        implementation v
    }

就等于加入了第三方引用

修改后的build.gradle如下

apply plugin: 'com.android.application'
apply plugin: 'com.jakewharton.butterknife'

def sc = rootProject.ext.SigningConfigs
def dc = rootProject.ext.DefaultConfig
def r = rootProject.ext.Release
def d = rootProject.ext.Debug
def dep = rootProject.ext.Dependencies

android {
    //签名配置
    signingConfigs {
        //签名Name
        config {
            //签名别名
            keyAlias sc.keyAlias
            //签名别名密码
            keyPassword sc.keyPassword
            //签名文件位置
            storeFile file(sc.storeFile)
            //签名密码
            storePassword sc.storePassword
        }
    }
    //开发环境版本号
    compileSdkVersion 26
    //默认配置
    defaultConfig {
        //Id
        applicationId "com.gjn.mydemo"
        //最小支持版本号
        minSdkVersion 19
        //运行版本号
        targetSdkVersion 25
        //appCode
        versionCode dc.versionCode
        //app版本号
        versionName dc.versionName
        //测试相关
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    //Build类型 默认有release和debug两个版本
    buildTypes {
        release {
            //是否开始混淆
            minifyEnabled false
            //混淆文件路径
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //打包时候调用的签名
            signingConfig signingConfigs.config
            //在BuildConfig生成一个String类型的Host=release_Host
            //即 public static final String Host = "release_Host";
            buildConfigField "String", "Host", "\"${r.Host_bcf}\""
            //编译之后会在res文件中的string.xml中加入一个string类型的app_name1=myMode
            //即 myMode
            resValue "string", "app_name1", "${r.appname_res}"
            //修改build之后的app名称
            //这边编译出来的名字是 release_1.0.apk
            //这个写法是Android Studio 3.0之后的方法
            android.applicationVariants.all { variant ->
                variant.outputs.all {
                    outputFileName = "${variant.name}_${variant.versionName}.apk"
                }
            }
        }
        debug {
            //为Id添加后缀 这边生成新的Id为com.gjn.mydemo.debug
            applicationIdSuffix ".debug"
            //这边下面和上面是一样

            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            buildConfigField("String", "Host", "\"${d.Host_bcf}\"")
            resValue("string", "app_name1", "${d.appname_res}")

            //占位符 替换AndroidManifest.xml 中的${test_key}字符
            //AndroidManifest.xml中的源代码为
            //
            //替换之后
            //
            manifestPlaceholders = ["test_key": "${d.test_key_mp}"]
        }
    }
    //多版本
    productFlavors{
        //dev版本
        dev{
            manifestPlaceholders = ["test_key": "${r.test_key_mp}"]
        }
        //free版本
        free{
            //这边在提下,由于free也会有release和debug两个版本
            //release的Id为com.gjn.mydemo.free
            //debug的Id为com.gjn.mydemo.free.debug
            applicationIdSuffix ".free"
            manifestPlaceholders = ["test_key": "free_key"]
        }
    }
    //遍历了全部版本
    productFlavors.all{
        //设置统一Code Android Studio 3.0之后需要设置这个属性 不然构建多版本的时候会报错
        flavorDimensions("versionCode")
    }
}
//导入第三方之类的jar aar 等 就不说了
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0'
    dep.each{ k,v->
        implementation v
    }
}

这样就把一些build.gradle中的配置分离出来了。到时候需要修改的时候,大部分只需要修改config文件就好了。其实优化下来,也就导入第三方库这块算是优化了(:з」∠)


Gradle打包

关于说打包之前,先说下Gradle的3个操作
复制Copy
删除Delete
压缩Zip

  • Copy

下面做一个任务,将/src/main/xml下的*.xml文件复制到/build/xml文件夹下

task CopyXml(type: Copy){
    includeEmptyDirs = false
    destinationDir = file('build')
    from( 'src/main/xml') {
        include '**.xml'
        into ('xml')
    }
}
[AS3.0.1]Gradle代码整合优化_第1张图片
效果
  • Delete

删除任务就是吧刚才的文件夹删除

task DeleteXml(type: Delete){
    delete 'build/xml', 'src/main/xml'
    followSymlinks = true
}

效果就不截图了。就是删除掉了两个文件夹

  • Zip

压缩任务。将app目录下的app.iml文件压缩到build目录下的adc.zip中的zip文件夹下。

task ZipTest(type: Zip){
    destinationDir = file('build')
    archiveName =  'abc.zip'

    from('.'){
        include('app.iml')
        into('zip')
    }
}
[AS3.0.1]Gradle代码整合优化_第2张图片
压缩结果

[AS3.0.1]Gradle代码整合优化_第3张图片
压缩包

知道了上面3个操作。就可以开始进行Gradle打包操作了!

以下项目example为例子原例子代码

.
├── example
│   ├── build.gradle
│   ├── example.iml
│   ├── proguard-rules.pro
│   └── src
├── libs
│   ├── armeabi
│   ├── armeabi-v7a
│   ├── com.umeng.fb.5.3.0.jar
│   ├── mips
│   └── x86
├── releasenote.txt
└── res
    ├── anim
    ├── drawable
    ├── drawable-xhdpi
    ├── layout
    ├── values
    └── values-zh

首先我们要知道,打包一个jar需要哪些步骤

  1. 编译工程(源代码)导出jar文件
  2. 复制"example"工程到"outputs/example"目录
  3. 复制jar文件到"outputs/libs"目录
  4. 复制资源文件到"outputs/res"目录
  5. 把 "outputs" 目录压缩成 zip 文件

之后就可以写入代码了

task dabao(type:Zip, dependsOn:build) { 
    destinationDir = file('outputs') 
    duplicatesStrategy = 'exclude' 
    archiveName = 'com.umeng.fb.' + android.defaultConfig.versionName + '.zip' 
    
    from('/'){ 
        include 'releasenote.txt' 
    } 
    into('example') { 
        from '../example' exclude '**/build/**' 
    } 
    from('src/main/res'){ 
        into 'res' 
    } 
    from('libs'){ 
        into 'libs' 
    } 
    from(zipTree('build/outputs/aar/sdk-release.aar')){ 
       include 'classes.jar' 
       rename 'classes.jar','com.umeng.fb.' + android.defaultConfig.versionName + '.jar' 
       into 'libs' 
    }
}

资料

Gradle 完整指南(Android)
看不懂的build.gradle代码
学点Groovy来理解build.gradle代码
如果像写代码一样写Gradle脚本
Gradle使用技巧总结

你可能感兴趣的:([AS3.0.1]Gradle代码整合优化)