gradle

Android Gradle 基础知识

2019-08-29  本文已影响0人  A_9908

一、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 可以比作流水线上的机器人,每个机器人负责不同的事情,最终生成完整的构建产物

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 的项目层次,我们新建一个项目看一下

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 里引入了新的依赖配置,如下:

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

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

模块 app 中有一个类 ModuleApi

模块 module1 中有一个类 Module1Api

模块 module2 中有一个类 Module2Api

其依赖关系如下:

implementation 依赖 

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

api 依赖 

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

compileOnly 依赖 

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

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

runtimeOnly 依赖 

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

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的时候才会引入

上一篇下一篇

猜你喜欢

热点阅读