你真的了解 Gradle 吗?

本文为菜鸟窝作者 吴威龙 的连载

Gradle 是什么?

2013 年,Google 发布了全新的 Android 开发 IDE————Android Studio。然而, Android Studio 基于 IDEA,不管怎么说,这都是一个高逼格的 IDE。但核心应该是 Google 新推出的 Gradle 编译环境。

Gradle 用于替换 Eclipse 所使用的 ant 作为默认的 Android 编译系统,相对于 ant 编译工具,Gradle 吸纳了 ant 灵活的脚本特性、Maven 丰富的依赖管理策略和强大的插件式环境。

正是由于 Gradle 的强大,导致上手难度比 ant 大,这也是许多从 Eclipse 环境切换到 Android Studio 环境的开发者觉得有困难的原因。然而 Gradle 的强大在于让 Android 开发的依赖管理、库管理、渠道管理等都变得更加方便;

Gradle 学习方式以及资料

首先,Gradle 本身是基于 Groovy 脚本语言进行构建的,并通过 Domain Specific Language(DSL 语言)进行描述和控制构建逻辑。但是作为开发者,大可不必去深究 Groovy 脚本语言,只要能看懂,懂配置使用就好了。

这里推荐几个比较官方的介绍文档:

医生书中推荐的那个链接失效了,网上找到了这个,应该算不错的。

在文末也附上几个超链接,有兴趣可以去戳戳。

一个 Android 项目中的文件结构(AS 而非 Eclipse)

项目文件目录

再安利一个表格:

目录文件 定义
.gradle gradle项目产生文件(自动编译工具产生的文件)
.idea IDEA项目文件(开发工具产生的文件)
app 其中一个 module,复用父项目的设置,可与父项目拥有相同的配置文件
build 自动构建时生成文件的地方
gradle 自动完成 gradle 环境支持文件夹
.gitignore git源码管理文件
build.gradle gradle 项目自动编译的配置文件
gradle.properties gradle 运行环境配置文件
gradlew 自动完成 gradle 环境的 linux mac 脚本,配合 gradle 文件夹使用
gradlew.bat 自动完成 gradle 环境的 windows 脚本,配合 gradle 文件夹使用
local.properties Android SDK NDK 环境路径配置
*.iml IDEA 项目文件
setting.gradle gradle 项目的子项目包含文件

常用的 gradle 文件介绍

表格看起来很清晰,重点看加粗的几个目录文件,下面再简要说说常用的 gradle 的文件:

module app 里面的 build.gradle

Android Studio 自动创建的 module 默认生成的 build.gradle 文件,这个文件是开发中打交道最多的一个文件。

如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.veyron.www.money"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:design:25.1.1'
    compile 'com.android.support:cardview-v7:25.1.1'
    compile 'com.android.support:appcompat-v7:25.1.1'
    compile 'com.github.d-max:spots-dialog:0.4@aar'
    testCompile 'junit:junit:4.12'
}

Gradle 使用的是 DSL 语言,也有翻译为领域特定语言。有的书籍建议理解的时候直接把 apply plugin、android、dependencies 看成一个个独立的 “领域” 即可。但我认为把 apply plugin、android、dependencies 当成为代码块(特定标签)也未尝不可。

apply plugin 代码块

apply plugin: 'com.android.application'

apply plugin 描述 Gradle 所引入的插件,这里表示该 module 是一个 Android Application。插件里面包含了 Android 项目相关的所有工具。

android 代码块

描述了该 Android module 构建过程中所用到的所有参数。默认情况下,IDE 会自动创建 compileSdkVersion、buildToolsVersion 两个参数,分别对应编译的 SDK 版本和 Android build tools 版本。而在 android 代码块内,系统还默认创建了两个代码块———— defaultConfig 和 buildTypes,这两个代码块后面文章在具体解释。

dependencies 代码块

描述了该 Android module 构建过程中所依赖的所有库,库可以是以 jar 的形式进行依赖,或者是使用 Android 推荐的 aar 形式进行依赖。aar 相对于 jar 具有不可比拟的优势,不仅配置依赖更简单,而且可以将图片的资源文件放入 aar 中供主项目依赖,几乎等于依赖了源码。Gradle 对于依赖关系的处理,就是向调用者屏蔽所有的依赖关系,主项目只需要依赖该 aar 库项目,而不需要知道 aar 项目对于其他库的依赖。

gradle 文件夹

定义:用于保存 gradle 下载路径的配置文件位置,用于没有gradle环境的环境初始化使用。

gradle 文件夹包括如下:

gradle-wrapper.propertes      //gradle-wrapper 配置文件
gradle-wrapper.jar            //gradle-wrapper 核心 jar


关于这个文件夹的介绍网上并不多,查阅多篇文章后汲取到一些有价值的东西就是关于 gradle-wrapper.propertes 文件中各个属性的一个介绍。相信通过这些配置属性的介绍,能够对这个文件夹的作用有一个基本的认识。

首先,打开该配置文件,内容如下:

#Mon Dec 28 10:00:20 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

下面一个个介绍

1.distributionUrl

distributionUrl 是要下载的 gradle 的地址,使用哪个版本的 gradle,就在这里修改。

gradle 有 3 种版本:(当然这个不了解也没关系)

gradle-xx-all.zip 是完整版,包含了各种二进制文件,源代码文件,和离线的文档。例如,https://services.gradle.org/distributions/gradle-2.14.1-all.zip

gradle-xx-bin.zip 是二进制版,只包含了二进制文件(可执行文件),没有文档和源代码。例如,https://services.gradle.org/distributions/gradle-2.14.1-bin.zip

gradle-xx-src.zip 是源码版,只包含了 Gradle 源代码,不能用来编译你的工程。例如,https://services.gradle.org/distributions/gradle-2.14.1-src.zip

如果只是为了编译,可以不用完整版,只需要二进制版即可,例如,gradle-2.14.1-bin.zip。

2.另外四个属性 (当然不了解也没关系)

zipStoreBase 和 zipStorePath 组合在一起,是下载的 gradle-2.14.1-all.zip 所存放的位置。
zipStorePath 是 zipStoreBase 指定的目录下的子目录。

distributionBase 和 distributionPath 组合在一起,是解压 gradle-2.14.1-all.zip 之后的文件的存放位置。
distributionPath 是 distributionBase 指定的目录下的子目录。

下载位置可以和解压位置不一样。

zipStoreBase 和distributionBase 有两种取值:GRADLE_USER_HOME 和 PROJECT。

其中,GRADLE_USER_HOME 表示用户目录。
在 windows 下是 %USERPROFILE%/.gradle,例如C:\Users<user_name>.gradle\。
在 Linux下是 $HOME/.gradle,例如~/.gradle。

PROJECT 表示工程的当前目录,即 gradlew 所在的目录。

3.各项属性的整体含义:

(1) 去 services.gradle.org/distributions/gradle-2.14.1-all.zip 下载 gradle 的 2.14.1 版本,是完整版本。

(2) 下载的 gradle-2.14.1-all.zip 存放到 C:\Users<user_name>.gradle\wrapper\dists 目录中。
(注:具体还有2级目录,即全路径为C:\Users<user_name>.gradle\wrapper\dists\gradle-2.14.1-all.zip<url-hash>\,gradle-2.14.1-all.zip 目录是根据下载的 gradle 的文件名来定的,<url-hash>目录名是根据 distribution url 路径字符串计算 md5 值得来的,具体参考 PathAssembler.Java 中的 rootDirName() 和 getHash(),PathAssembler.java 的位置见本文最后的参考路径)

(3) 解压 gradle-2.14.1-all.zip,将解压后的文件存放到 C:\Users<user_name>.gradle\wrapper\dists中。(注:具体还有2级目录,同上)

推荐一博文
gradle-wrapper.propertes 各属性的介绍

gradle wrapper分析

项目全局的 build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

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

buildscript 代码块中,Gradle 指定了使用 jcenter 代码仓库,同时声明依赖的 Android Gradle 插件的版本。
allprojects 代码块中,开发者可以为项目整体配置一些属性。

这里补充一下,jcenter 是什么呢?其实就是一个公共的中央仓库,如 maven 中央仓库,以供别人方便地集成使用。

如果有兴趣让别人使用你的源码的可以搜搜:使用 Gradle 发布 Android 开源项目到 Jcenter.

gradle.priperties

Android Studio 默认生成的 gradle.priperties 如下:

# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

上面的英文注释比较多,那么富有探究精神,有打破砂锅问到底,或者有强迫症的同学就受不了了,一定得弄出个所以然来。

下面就用我蹩脚的英语翻译下:

#项目范围 Gradle 设置。
# IDE(例如Android Studio)用户:
# Gradle 设置通过 IDE 配置 *将会覆盖*
#任何设置在该文件中指定。
#更多细节关于如何配置您的构建环境的访问
# http://www.gradle.org/docs/current/userguide/build_environment.html
#指定 JVM 参数用于守护进程。
#这个 setting 尤其有用的调整内存的设置。

org.gradle.jvmargs = -Xmx1536m


#配置时,它将运行在孵化并行模式。
#这个选项应该只被用于分离的项目。更多细节,请访问
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html秒:decoupled_projects
# org.gradle.parallel = true

简而言之,就是一个配置全局的管理文件。
配置 gradle 运行环境的文件,比如配置 gradle 运行模式,运行时 jvm 虚拟机的大小。

举个栗子:
一般大型的项目都是拆分进行模块化开发的,这时候每个模块在合并的时候容易有冲突(假如版本冲突),或者需要改版本的时候比较麻烦,需要一个一个地方去改,这时候配置全局的 gradle.properties 文件就显得异常有帮助了。

在项目 gradle.properties 配置文件修改栗子如下:

# Project-wide Gradle settings.
#添加ndk支持(按需添加)
android.useDeprecatedNdk=true
# 应用版本名称
VERSION_NAME=1.0.0
# 应用版本号
VERSION_CODE=100
# 支持库版本
SUPPORT_LIBRARY=24.2.1
# MIN_SDK_VERSION
ANDROID_BUILD_MIN_SDK_VERSION=14
# TARGET_SDK_VERSION
ANDROID_BUILD_TARGET_SDK_VERSION=24
# BUILD_SDK_VERSION
ANDROID_BUILD_SDK_VERSION=24
# BUILD_TOOLS_VERSION
ANDROID_BUILD_TOOLS_VERSION=24.0.3

这样就为项目配置了全局属性,其他模块就可以任性的使用了,需要改动的时候只需要在这个全局的配置文件中一键修改即可,是不是很嗨森啊。

各个模块的 build.gradle 如下写即可:

android {
    compileSdkVersion project.ANDROID_BUILD_SDK_VERSION as int
    buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
 
    defaultConfig {
        applicationId project.APPLICATION_ID
        versionCode project.VERSION_CODE as int
        versionName project.VERSION_NAME
        minSdkVersion project.ANDROID_BUILD_MIN_SDK_VERSION as int
        targetSdkVersion project.ANDROID_BUILD_TARGET_SDK_VERSION as int
    }
}
 
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    //这里注意是双引号
    compile "com.android.support:appcompat-v7:${SUPPORT_LIBRARY}"
    compile "com.android.support:design:${SUPPORT_LIBRARY}"
    compile "com.android.support:recyclerview-v7:${SUPPORT_LIBRARY}"
    compile "com.android.support:support-annotations:${SUPPORT_LIBRARY}"
    compile "com.android.support:cardview-v7:${SUPPORT_LIBRARY}"
    compile "com.android.support:support-v4:${SUPPORT_LIBRARY}"
}

这里可以看到有些属性后面有 as int ,这是因为原本的配置应该都是默认是字符串,然后用 as int 就可以轻松转换成 int 类型了。

这个栗子也是网上找的,链接放在文末哈,这是对作者的一个基本的尊重。

local.properties

Android Studio 默认生成的 local.properties 如下:

## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file should *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=D\:\\adt-bundle-windows-x64\\android-sdk-windows

上面的英文注释已经很清楚了,这里就不秀我的英语翻译水平了。简单转述就是,Android Studio 自动创建的工程中,IDE 自动配备了本地配置文件,并且设置了 sdk.dir 属性。也就是配置了 Android_Home 环境变量,所以 IDE 能够自动生成这个配置文件。一般情况都不用修改这个配置文件,除非你一定要重新制定一个 SDK 路径。

setting.gradle

项目的子项目包含文件,声明当前目录下含有什么 module,当然你的 app 底下加上这样的文件,也能继续在 app 底下加 module。整个 project 就是一个大的 module,每个 module 下面还能包含相应的 module。

总结

看完上面的介绍,相信对 gradle 这个强大的项目构建工具有了一个比较具体的理解了。
写这篇文章时参考了很多 gradle 相关的博文和医生(徐宜生)名著《神兵利器》的内容,正是站在巨人的肩膀上,我可以看得更远!感恩!

本文哪里写的不对的地方,欢迎指出哈!

参考文献

更多内容,请关注菜鸟窝(微信公众号ID: cniao5),程序猿的在线学习平台。 转载请注明出处,本文出自菜鸟窝,原文链接http://www.cniao5.com/forum/thread/9b50d2fc11d111e782d600163e0230fa

关注公众号免费领取“N套客户端实战项目教程”
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容