Android Gradle 基础知识

一、gradle 是什么

官方解释是:

Gradle is an open-source build automation tool focused on flexibility and performance. Gradle build scripts are written using a Groovy or Kotlin DSL.

可以从三个角度来理解

1. gradle 是一个自动化构建工具 

gradle 是通过组织一系列 task 来最终完成自动化构建的,所以 task 是 gradle 里最重要的概念

我们以生成一个可用的 apk 为例,整个过程要经过 资源的处理,javac 编译,dex 打包,apk 打包,签名等等步骤,每个步骤就对应到 gradle 里的一个 task

gradle 可以类比做一条流水线,task 可以比作流水线上的机器人,每个机器人负责不同的事情,最终生成完整的构建产物

Android Gradle 基础知识_第1张图片

2. gradle 脚本使用了 groovy 或者 kotlin DSL 

gradle 使用 groovy 或者 kotlin 编写,不过目前还是 groovy 居多

那什么是 DSL 呢?DSL 也就是 Domain Specific Language 的简称,是为了解决某一类任务专门设计的计算机语言

DSL 相对应的是 GPL (General-Purpose Language),比如 java

与 GPL 相比起来,DSL 使用简单,定义比较简洁,比起配置文件,DSL 又可以实现语言逻辑

对 gradle 脚本来说,他实现了简洁的定义,又有充分的语言逻辑,以 android {} 为例,这本身是一个函数调用,参数是一个闭包,但是这种定义方式明显要简洁很多

3. gradle 基于 groovy 编写,而 groovy 是基于 jvm 语言 

gradle 使用 groovy 编写,groovy 是基于 jvm 的语言,所以本质上是面向对象的语言,面向对象语言的特点就是一切皆对象,所以,在 gradle 里,.gradle 脚本的本质就是类的定义,一些配置项的本质都是方法调用,参数是后面的 {} 闭包

比如 build.gradle 对应 Project 类,buildScript 对应 Project.buildScript 方法

二、gradle 项目分析

关于 gradle 的项目层次,我们新建一个项目看一下

Android Gradle 基础知识_第2张图片

2.1 settings.gradle

settings.gradle 是负责配置项目的脚本对应Settings 类,gradle 构建过程中,会根据 settings.gradle 生成 Settings 的对象

对应的可调用的方法在文档里可以查找其中几个主要的方法有:

include(projectPaths)

includeFlat(projectNames)

project(projectDir)

一般在项目里见到的引用子模块的方法,就是使用 include,这样引用,子模块位于根项目的下一级

include ':app'

如果想指定子模块的位置,可以使用 project 方法获取 Project 对象,设置其 projectDir 参数

include ':app'

project(':app').projectDir = new File('./app')

2.2 rootproject/build.gradle

build.gradle 负责整体项目的一些配置,对应的是 Project 类gradle 构建的时候,会根据 build.gradle 生成 Project 对象,所以在 build.gradle 里写的 dsl,其实都是 Project 接口的一些方法,Project 其实是一个接口,真正的实现类是 DefaultProject 

build.gradle 里可以调用的方法在Project 可以查到其中几个主要方法有:

buildscript // 配置脚本的 classpath

allprojects // 配置项目及其子项目

respositories // 配置仓库地址,后面的依赖都会去这里配置的地址查找

dependencies // 配置项目的依赖

以 EasyGradle 项目来看

buildscript { // 配置项目的 classpath

    repositories {  // 项目的仓库地址,会按顺序依次查找

        google()

        jcenter()

        mavenLocal()

    }

    dependencies { // 项目的依赖

        classpath 'com.android.tools.build:gradle:3.0.1'

        classpath 'com.zy.plugin:myplugin:0.0.1'

    }

}

allprojects { // 子项目的配置

    repositories {

        google()

        jcenter()

        mavenLocal()

    }

}

2.3 module/build.gradle

build.gradle 是子项目的配置,对应的也是 Project 类

子项目和根项目的配置是差不多的,不过在子项目里可以看到有一个明显的区别,就是引用了一个插件 apply plugin "com.android.application",后面的 android dsl 就是 application 插件的 extension,关于 android plugin dsl 可以看

 android-gradle-dsl 

其中几个主要方法有:

compileSdkVersion // 指定编译需要的 sdk 版本

defaultConfig // 指定默认的属性,会运用到所有的 variants 上

buildTypes // 一些编译属性可以在这里配置,可配置的所有属性在 这里

productFlavor // 配置项目的 flavor

以 app 模块的 build.gradle 来看

apply plugin: 'com.android.application' // 引入 android gradle 插件

android { // 配置 android gradle plugin 需要的内容

    compileSdkVersion 26

    defaultConfig { // 版本,applicationId 等配置

        applicationId "com.zy.easygradle"

        minSdkVersion 19

        targetSdkVersion 26

        versionCode 1

        versionName "1.0"

    }

    buildTypes {

        release {

            minifyEnabled false

            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        }

    }

    compileOptions { // 指定 java 版本

        sourceCompatibility 1.8

        targetCompatibility 1.8

    }

    // flavor 相关配置

    flavorDimensions "size", "color"

    productFlavors {

        big {

            dimension "size"

        }

        small {

            dimension "size"

        }

        blue {

            dimension "color"

        }

        red {

            dimension "color"

        }

    }

}

// 项目需要的依赖

dependencies {

    implementation fileTree(dir: 'libs', include: ['*.jar']) // jar 包依赖

    implementation 'com.android.support:appcompat-v7:26.1.0' // 远程仓库依赖

    implementation 'com.android.support.constraint:constraint-layout:1.1.3'

    implementation project(':module1') // 项目依赖

}

2.4 依赖

在 gradle 3.4 里引入了新的依赖配置,如下:

Android Gradle 基础知识_第3张图片

还是以 EasyGradle 为例,看一下各个依赖的不同:

项目里有三个模块:app,module1, module2

模块 app 中有一个类 ModuleApi

模块 module1 中有一个类 Module1Api

模块 module2 中有一个类 Module2Api

其依赖关系如下:


Android Gradle 基础知识_第4张图片

implementation 依赖 

当 module1 使用 implementation 依赖 module2 时,在 app 模块中无法引用到 Module2Api 类


Android Gradle 基础知识_第5张图片

api 依赖 

当 module1 使用 api 依赖 module2 时,在 app 模块中可以正常引用到 Module2Api 类,如下图


Android Gradle 基础知识_第6张图片

compileOnly 依赖 

当 module1 使用 compileOnly 依赖 module2 时,在编译阶段 app 模块无法引用到 Module2Api 类,module1 中正常引用,但是在运行时会报错

反编译打包好的 apk,可以看到 Module2Api 是没有被打包到 apk 里的


Android Gradle 基础知识_第7张图片

runtimeOnly 依赖 

当 module1 使用 runtimeOnly 依赖 module2 时,在编译阶段,module1 也无法引用到 Module2Api


Android Gradle 基础知识_第8张图片

2.5 flavor

在介绍下面的流程之前,先明确几个概念,flavor,dimension,variant

在 android gradle plugin 3.x 之后,每个 flavor 必须对应一个 dimension,可以理解为 flavor 的分组,然后不同 dimension 里的 flavor 两两组合形成一个 variant

举个例子

如下配置:

flavorDimensions "size", "color"

productFlavors {

    big {

        dimension "size"

    }

    small {

        dimension "size"

    }

    blue {

        dimension "color"

    }

    red {

        dimension "color"

    }

}

那么生成的 variant 对应的就是 bigBlue,bigRed,smallBlue,smallRed

每个 variant 可以对应的使用 variantImplementation 来引入特定的依赖,比如:bigBlueImplementation,只有在 编译 bigBlue variant的时候才会引入

你可能感兴趣的:(Android Gradle 基础知识)