Gradle在Android下的详解及最佳实践

  • 阅读本文需要10min+
    关键字
    Gradlegroovy

目录

  • 前言
  • 简介
  • groovy
    1. 简介
    2. 数据语法
    3. 数据类型
  • gradle
    1. 简介
    2. 依赖管理
    3. 几个常用Task
    4. 新版本gradle属性介绍( android plugin 3.0.0搭配Gradle 3.4版本以上)
  • 最佳实践
    1. 实践一
    2. 实践二
  • 参考

前言

Gradle的知识体系非常庞大,市面上有专门讲解的书籍,如果想全面了解可以购买书籍或者查看网上的系列教程。本文只带你入门以及熟悉在Android下常见的使用场景。

简介

gradle还是glide?作为一个Android开发者,有时候会把两者给拼写错误,前者也就是本文的主角,是一个自动化构建(build)的工具,说到构建,有的同学可能不太理解,初略的理解就是根据输入的信息执行一些操作,然后得到目标产物的过程称为构建。构建不同于编译工具,它用于组织编译,单元测试,发布等操作。这里提到构建,就顺便提一下构建工具的发展史

  1. Makefile
    这是什么鬼,我也不熟,不过据说是最元老的构建工具,至今仍然是Linux上C/C++开发最流行的构建工具,上了G界别的Android系统的开源项目就是由Makefile构建
  2. Ant
    Java出世,是为跨平台而生,而Makefile成了一个大大的绊脚石,Java开发人员急切的需要一个跨平台的构建工具,最好能在JVM上运行,于是Ant诞生了,Ant使用的xml文件格式
  3. Maven
    Ant出现,为很多Java开发者带来了福音,不过伴随着软件行业的日益发展,规模变大,大家发现Ant不够用,于是Maven出世,Maven他使用XML文件格式(pom.xml)
  4. Gradle
    2004年,Maven发布后,非常受Java开发人员爱戴,然而,软件史上,再伟大的项目都有他丧失光芒的一天,于是gradle出世了,在他问世之后,Google迅速把Android的编译环境迁移到gradle,当你搜索gradle时,你应该会有这样的感觉,为何人们都如此爱好这个工具,其中很大一部分原因是gradle使用了基于Groovy的DSL语言作为构建脚本语言的而不是以往的XML。

PS: 有关构建工具的发展的详细历史,可以参考[这篇文章](http://blog.csdn.net/yanquan345/
article/details/46710869)

groovy

简介

Groovy是一种动态语言,和Java一样,运行在Java虚拟机中,简单粗暴的理解,可以认为Groovy扩展了Java语言,除了语言和Java相通外,Groovy有时候又像一种脚本语言。当我执行 Groovy 脚本时,Groovy 会先将其编译成 Java 类字节码,然后通过 Jvm 来执行这个 Java 类,实际上,由于 Groovy Code 在真正执行的时候已经变成了 Java 字节码,所以 JVM 根本不知道自己运行的是 Groovy 代码。

使用Groovy 还可以开发Android应用,可以参考[这篇文章](https://www.jianshu.com/p/
399ae2d0f313)

数据语法

既然Groovy是一种语言,它必然有他的语言编写规则,下面只粗略的介绍,更多细节可以查看官方文档

  1. Groovy 注释标记和 Java 一样,支持//或者/**/
  2. Groovy 语句可以不用分号结尾。
  3. Groovy 中支持动态类型,即定义变量的时候可以不指定其类型。Groovy 中,变量定义可以使用关键字 def。注意,虽然 def 不是必须的,但是为了代码清晰,建议还是使用 def 关键字
def variable1 = 1   //可以不使用分号结尾  
def varable2 = "I am a person"
def  int x = 1   //变量定义时,也可以直接指定类型  
  1. 函数定义时,参数的类型也可以不指定。
String testFunction(arg1,arg2){//无需指定参数类型  
  ...
}

数据类型

  1. 一个是 Java 中的基本数据类型。
  2. 另外一个是 Groovy 中的容器类。
  3. 最后一个非常重要的是闭包。

这一块的知识点详细可以查看[这个地址](http://wiki.jikexueyuan.com/project/deep-android- gradle/three-three.html),如果你想详细了解Groovy这门语言,可以查看IBM的中文教程,更多细节可以查看官方文档

gradle

简介

Gradle是一个框架,它定义了一套自己的规则。Gradle 中,每一个待编译的工程都叫一个 Project。我们点击build.gradle会跳转到gradle源码Project.java类中,每一个 Project 在构建的时候都包含一系列的 Task。比如一个 Android APK 的编译可能包含:Java 源码编译 Task、资源编译 Task、JNI 编译 Task、lint 检查 Task、打包生成 APK 的 Task、签名 Task 等(在后面我们会专门介绍几个常用Task)。
Android Studio几个有关gradle的配置文件,如下图

《Gradle在Android下的详解及最佳实践》 gradle配置图

更多细节可以查看这里,或者查看官方文档

依赖管理

首先我们看下面一段gradle代码

  apply plugin: 'com.android.application'
  repositories {
          jcenter()
      }
  dependencies {
      compile 'com.android.support:appcompat-v7:26.+‘
      testCompile 'junit:junit:4.12'
}

这段脚本是什么意思呢?首先com.android.support:appcompat-v7:26.+(仓库中26版本下的最新版,不过官方不建议这么写)这货是编译期必须依赖,并且它相关的依赖也会一起加载进来(v4包),该脚本同时还申明项目测试阶段需要4.12版本的junit。同时告诉gradle可以去jcenter仓库去加载这些依赖,下面将较详细的描述。

依赖配置

  1. 按依赖的作用分为以下几部分
    • compile
      编译范围依赖在所有的classpath范围可用,同时它们也会被打包到apk中
    • apk
      apk的意思是apk中存在,但是不会加入编译中(用的比较少)
    • provided
      提供编译支持,但是不会写入apk
    • runtime
      runtime依赖在运行和测试系统的时候需要,编译的时候不需要
    • testCompile&androidTestCompile
      测试编译需要附加的依赖

PS: 在gradle3.4版本,以上配置关键字被调整优化了,下面会讲解到。
测试运行期需要的依赖

  1. 按依赖的加入方式分为两种
    (1) 远程依赖
    远程依赖指的是library被放置到远程(可以是自己的maven库或者是maven中心库或jcenter),需要的时候在maven方法加入url地址
repositories {
       maven {
           url "http://repo.acmecorp.com/maven2"
       }
}

(2) 本地依赖

  • 文件依赖
dependencies {
       compile fileTree(dir: 'libs', include: ['*.jar'])
}

默认新建Android项目会自动生成这端代码,这段代码的意思是把libs文件夹下的所有jar文件添加到编译路径以及最后的apk文件(如果你想添加单个文件可以compile files('libs/okhttp.jar')

  • arr依赖
    首先得先把arr文件拷贝到自己创建的一个文件夹(比如arrs),然后把arr文件拷贝到该文件夹里,然后添加该文件夹作为依赖库
repositories {
    flatDir {
        dirs 'aars' 
    }
}

最后把该文件夹下的arr作为依赖

dependencies {
       compile(name:'libraryname', ext:'aar')
}

这个会告诉gradle,在aars文件夹下,添加一个叫做libraryname的文件,且其后缀是aar的作为依赖。

  • 工程依赖
    如果把其他工程作为模块,需要在setting.gradle文件添加
include ':app', ':library'

然后在module使用该依赖

 dependencies {
       compile project(':library')
  }
  • narive包(so包)
    使用c/c++编写的library会叫做so包,Android插件默认支持native包,把.so文件放入对应的文件夹中:
app
   ├── AndroidManifest.xml
   └── jniLibs
       ├── armeabi
       │   └── nativelib.so
       ├── armeabi-v7a
       │   └── nativelib.so
       ├── mips
       │   └── nativelib.so
       └── x86
           └── nativelib.so

几个常用Task

在Android Studio 的Terminal输入”./gradlew tasks –all”,数据一大串task,如下(图片太大,我把其分为三部分)

《Gradle在Android下的详解及最佳实践》 图1

《Gradle在Android下的详解及最佳实践》 图2

《Gradle在Android下的详解及最佳实践》 图3

这里列出里Project ArchitectureSample支持的Task(Task 也可以自定义),这里简介一下我常用的一些Task,更多命令可以查看gradle官方文档

./gradlew -v //查看构建版本
./gradlew assembleDebug  //编译并打Debug包
./gradlew assembleRelease // 编译并打Release的包
./gradlew installRelease  //  Release模式打包并安装
./gradlew uninstallRelease //卸载Release模式包
./gradlew -q app:dependencies //查看app module下的依赖
./gradlew install[productFlavorsName] app:assembleDebug//结合productFlavors多渠道打包

注意:在window下可以直接运行 gradlew 如果是Linux 或者 mac 命令为 gradle gradlew 这里都简写成 ./gradle

新版本gradle属性介绍( android plugin 3.0.0搭配Gradle 3.4版本以上)

  • Implementation vs compile
    升级到新版本的gradle,发现Android Studio 新建工程发现默认添加的依赖改成了Implementation,而不是之前的compile,同样替换的有 api 替换compile compileOnly 替换provided ,runtimeOnly替换apk,Implementation较compile有什么改进呢,简单一句话就是加快了编译速度,稍微复杂的一句话就是Implementation较compile改动底层library不需要重新编译整个Project,更细节可以看这篇文章,更多新特性可以查看相应官方文档

ps:如果没有升级的建议尽快升级,为了更好的体验,下面的截图取自官方文档是不同版本编译速度的比较
《Gradle在Android下的详解及最佳实践》 gradle不同版本速度比较

最佳实践

实践一

在module的build.gradle

android {
    compileSdkVersion project.COMPILE_SDK as int
    buildToolsVersion project.BUILD_TOOLS_VERSION

    defaultConfig {
        minSdkVersion project.MIN_SDK as int
        targetSdkVersion project.TARGET_SDK as int
        .....
        }
        ......
      }
      
      dependencies {
       compile "com.android.support:appcompat-v7:${SUPPORT_LIBRARY}"
       compile "com.squareup.retrofit2:retrofit:${retrofit}"
       compile "com.squareup.retrofit2:converter-gson:${retrofit}"
       compile "com.squareup.retrofit2:converter-scalars:${retrofit}"
       compile "com.squareup.okhttp3:okhttp:${OKHTTP}"
       compile "com.squareup.okhttp3:logging-interceptor:${OKHTTP}"
    ......
    }

在gradle.properties直接定义

COMPILE_SDK=25
MIN_SDK=16
TARGET_SDK=25
BUILD_TOOLS_VERSION=25.0.3
SUPPORT_LIBRARY=25.0.1
OKHTTP=3.6.0
retrofit = 2.2.0

实践二

在project根目录新建versions.gradle

ext {

    android = [
               compileSdkVersion       : 25,
               buildToolsVersion       : "25.0.3",
               minSdkVersion           : 15,
               targetSdkVersion        : 25,
               versionCode             : 130,
               versionName             : "2.1.5"
    ]

     version = [
                   androidSupportSdkVersion: "25.4.0",
                   retrofitSdkVersion      : "2.3.0",
                   glideSdkVersion         : "4.0.0",
                   butterknifeSdkVersion   : "8.7.0",
                   rxlifecycleSdkVersion   : "1.0",
                   rxlifecycle2SdkVersion  : "2.1.0",
                   espressoSdkVersion      : "2.2.2"
        ]
        
         dependencies = [
                //support
                "appcompat-v7"             : "com.android.support:appcompat-v7:${version["androidSupportSdkVersion"]}",
                "design"                   : "com.android.support:design:${version["androidSupportSdkVersion"]}",
                "support-v4"               : "com.android.support:support-v4:${version["androidSupportSdkVersion"]}",
                "cardview-v7"              : "com.android.support:cardview-v7:${version["androidSupportSdkVersion"]}",
                "annotations"              : "com.android.support:support-annotations:${version["androidSupportSdkVersion"]}",
                "recyclerview-v7"          : "com.android.support:recyclerview-v7:${version["androidSupportSdkVersion"]}",
                "glide"                    : "com.github.bumptech.glide:glide:${version["glideSdkVersion"]}",
                "retrofit"                 : "com.squareup.retrofit2:retrofit:${version["retrofitSdkVersion"]}",
                "gson"                     : "com.google.code.gson:gson:2.8.1"
   }

然后在project的build.gradle引入apply from: “config.gradle”,moudle 的build.gradle的代码如下

android {
    compileSdkVersion rootProject.ext.android["compileSdkVersion"]
    buildToolsVersion rootProject.ext.android["buildToolsVersion"]
    ......
     defaultConfig {
        applicationId "com.example.tml.gradle.demo"
        minSdkVersion rootProject.ext.android["minSdkVersion"]
        targetSdkVersion rootProject.ext.android["targetSdkVersion"]
        versionCode rootProject.ext.android["versionCode"]
        versionName rootProject.ext.android["versionName"]
        ......
    }
    }
    
    dependencies{

       compile(rootProject.ext.dependencies["appcompat-v7"]) {
            exclude module: 'support-annotations'
            exclude module: 'support-v4'
          }
      compile(rootProject.ext.dependencies["design"]) {
          exclude module: 'support-annotations'
          exclude module: 'appcompat-v7'
          exclude module: 'support-v4'
          }
      compile(rootProject.ext.dependencies["retrofit"]) {
          exclude module: 'okhttp'
          exclude module: 'okio'
          }
      compile(rootProject.ext.dependencies["retrofit"]) {
          exclude module: 'okhttp'
          exclude module: 'okio'
          }
      compile(rootProject.ext.dependencies["glide"]) {
          exclude module: 'support-v4'
      }
      compile rootProject.ext.dependencies["gson"]
        ......
    }

参考

http://wiki.jikexueyuan.com/project/deep-android-gradle/
http://avatarqing.github.io/Gradle-Plugin-User-Guide-Chinese-Verision/basic_project/README.html
https://docs.gradle.org/current/javadoc/
http://www.groovy-lang.org/api.html
https://developer.android.com/studio/releases/gradle-plugin.html
https://developer.android.com/studio/build/index.html?hl=zh-cn
https://juejin.im/entry/59476897da2f60006786029f
https://segmentfault.com/a/1190000004241503

    原文作者:文艺的程序狗
    原文地址: https://www.jianshu.com/p/edb724bdc762
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞