Android开发经验谈Android开发

Android中用到的Gradle原理是什么?

2020-05-30  本文已影响0人  Android进阶小麦

1. 前言

我们都知道利用Android Studio编写APP时,会使用Gradle这个工具,那么Gradle到底是什么呢?它在APP编写中起到什么作用呢?

Gradle是一个项目自动化建构工具。构建就是根据输入信息执行一系列操作,最后得到几个产出物(APK包)。

传统的构建工具有Ant和Maven,但他们有一些缺点,例如Maven使用XML来制定构建规则。XML虽然通俗易懂,但是很难在xml中描述if{某条件成立,编译某文件}/else{编译其他文件}这样有不同条件的任务。针对这类问题自然需要编程来解决,所以,Gradle选择了Groovy语言。

Gradle的另一个特点是它是一种DSL(Domain-Specific-Language),即特定领域语言,就是针对某一领域而产生的语言。DSL的好处是一句话可以包含很多意思,因为只针对特定领域解决问题。

Gradle当前其支持的语言限于Java、Groovy和Scala,计划未来将支持更多的语言。Gradle可以帮你管理项目中的差异,依赖,编译,打包,部署...,你可以定义满足自己需要的构建逻辑,写入到build.gradle中供日后复用,通俗的说:gradle是打包用的

1.1 Groovy基础

Groovy是个灵活的动态脚本语言,基于JVM虚拟机,语法和Java很相似,又兼容Java,且在此基础上增加了很多动态类型和灵活的特性,如支持闭包和DSL。Groovy的开发环境配置可以参考Groovy 环境配置,具体语言特性教程可以参考-Groovy教程

Groovy基于Java,又扩展了Java,运行过程中首先会先将其编译成Java类字节码,然后通过JVM来执行这个Java类。

1.2 Gradle介绍

Gradle是一个工具,也是一个编程框架。要弄清楚Gradle,则必须知道其组成的基本组件,Gradle中每个待被编译的工程叫Project,每个Project在构建时都包含一系列Task,如Android Studio构建过程中包括Java代码编译Task,资源编译Task,Lint规则检查Task,签名Task等等。

参考深入理解Android之Gradle

配置Gradle环境前,确保已经安装配置好Java环境,下载Gradle后解压并配置环境变量,具体可以参考-配置Gradle

下面是一个Gradle语言版的Hello word例子:

// Gradle版Hello word
// 新建build.gradle文件:
task hello{ // 定义一个任务Task名为hello
    doLast{ // 添加一个动作Action,表示在Task执行完毕后回调doLast闭包中的代码
        println'Hello World'//输出字符串,单双号均可
    }
}
// 命令行:
gradle hello // 执行build.gradle中名为Hello的任务
// 输出:
Hello World

总而言之,学习Gradle我们需要掌握Groovy语言,以及Gradle在Android Studio中的工作方式,工作流程,工作原理。

2. Android studio中的Gradle文件

Android Studio 会使用高级构建工具包 Gradle 来自动执行和管理构建流程,同时也允许开发者定义灵活的自定义版本配置。每个版本配置均可定义自己的一组代码和资源,同时重复利用应用各个版本的共用部分。

Gradle提供了一种编译、构建和打包 Android 应用或库的灵活方式。
一个Android Studio和Gradle的项目目录如下:

image

我们先来看看Android Gradle项目中那些涉及到gradle的文件分别是什么意思。

一个Android项目中所有文件的具体含义可参考Android开发者指南

2.1 Gradle wrapper(gradle包装)

上图中涉及到Gradle wrapper的部分如下所示,具体有上图中的gradle文件夹,gradlew文件和gradlew.bat批处理文件

|--gradle
|   |--wrapper
|        |--gradle-wrapper.jar
|        |--gradle-wrapper.properties
|--gradlew
|--gradlew.bat

gradle文件夹中包含wrapper,wrapper顾名思义是对Gradle的一层包装,便于在团队开发过程中统一Gradle构建的版本。

上面目录中gradlewgradlew.bat分别是Linux和Windows下的可执行脚本,gradle-wrapper.jar是具体业务逻辑实现的jar包,gradlew可执行脚本最终还是使用这个jar包来执行相关Gradle操作,gradle-wrapper.properties是配置文件,用于配置使用哪个版本的Gradle,配置文件中的具体内容如下所示:

#Wed Jun 19 10:09:08 GMT+08:00 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip

2.2 Settings.gradle (多工程配置)

此文件用于初始化以及工程树的配置,大多数用于配置子工程,在Gradle中多个工程是通过工程树来表示的,相当于我们在Android Studio看到的Project和Module概念一样,根工程相当于Project,子工程相当于Module,一个Project可以有很多Module,一个子工程只有在Setting.gradle中配置了才会生效。
配置举例:

// 添加:app和:common这两个module参与构建
include ':app' 
project(':app').projectDir = new File('存放目录')
include':common'
project(':common').projectDir = new File('存放目录')

如果不指定上述存放目录,则默认为是Settings.gradle其同级目录。

2.3 build.gradle文件(版本文件)

每个工程都会有build.gradle文件,该文件是该工程的构建入口,在此文件中可以对该工程进行配置,如配置版本,插件,依赖库等。
既然每个工程都有一个build文件,那么根工程也不例外,在根工程中可以对子Module进行统一配置,全局管理版本号或依赖库
build文件分为Project和Module两种,如下图所示:

image
  1. Project的build.gradle:整个Project的共有属性,包括配置版本、插件、依赖库等信息
  2. Module的build.gradle:各个module私有的配置文件

2.3.1 Project中build.gradle文件(顶层版本文件)

buildscript {
    // gradle脚本执行所需依赖仓库
    repositories {
        google()
        jcenter()

    }
    // gradle脚本执行所需依赖
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.1'
    }
}

allprojects {
    // 项目本身需要的依赖仓库
    repositories {
        google()
        jcenter()

    }
}

那么buildscript中的repositories和allprojects的repositories的作用和区别是什么呢?

  1. buildscript里是gradle脚本执行所需依赖,分别是对应的maven库和插件
  2. allprojects里是项目本身需要的依赖,比如我现在要依赖maven库的xx库,那么我应该将maven {url '库链接'}写在这里,而不是buildscript中,否则找不到所需要的库

参考 作者:CalvinNing -原文链接

2.3.2 Module中build.gradle文件(模块级版本文件)

此部分内容参考下文中3.3.2节。

2.4 gradle.properties(属性文件)

此文件主要在其中配置项目全局 Gradle 设置,如 Gradle 守护进程的最大堆大小。如需了解详情,请参阅构建环境

3. Gradle插件

3.1 插件介绍

Gradle的设计非常好,本身提供一些基本的概念和整体核心的框架,其他用于描述真实使用场景逻辑的都以插件扩展的方式来实现,比如构建Java应用,就通过Java插件来实现,那么自然构建Android应用,就通过Android Gradle插件来实现。

Gradle 提供了很多官方插件,用于支持Java、Groovy等工程的构建和打包。同时也提供了自定义插件机制,让每个人都可以通过插件来实现特定的构建逻辑,并可以把这些逻辑打包起来,分享给其他人。

Android Gradle插件是基于内置的Java插件实现的。Gradle插件的作用如下:

  1. 可以添加任务到项目,比如测试、编译、打包
  2. 可以添加依赖配置到项目,帮助配置项目构建过程中需要的依赖,比如第三方库等
  3. 可以向项目中现有的对象类型添加新的扩展属性和方法等,帮助配置和优化构建
  4. 可以对项目进行一些约定,比如约定源代码存放位置

3.2 插件种类及用法

3.2.1 插件种类

3.2.2 插件用法

下面分别说下二进制插件和脚本插件的使用方法,

id式:apply plugin:'plugin id'

类型式:apply plugin:org.gradle.api.plugins.JavaPlugin

简写式:apply plugin:JavaPlugin

3.3 Android Gradle插件

从Gradle的角度看,Android其实就是Gradle的一个第三方插件,它是由Google的Android团队开发的,Android 开发 IDE Android Studio 就采用 Gradle 构建项目。

3.3.1 Android Gradle插件分类

  1. App应用工程:生成可运行apk应用;插件id: com.android.application
  2. Library库工程:生成AAR包给其他的App工程公用,其使用方式和jar包一样,里面有相关的 Android 资源文件;插件id: com.android.library
  3. Test测试工程:对App应用工程或Library库工程进行单元测试;插件id: com.android.test

3.3.2 Android Gradle插件的应用

主要来看下Android Gradle的build.gradle配置文件:

// 插件id
apply plugin:'com.android.application'
// 自定义配置入口,后续详解
android{
    compileSdkVersion 23 // 编译Android工程的SDK版本
    buildToolsVersion "23.0.1" // 构建Android工程所用的构建工具版本

    defaultConfig{
        applicationId "com.example.myapplication" // 配置包名
        minSdkVersion 14 // 最低支持的Android系统的Level
        targetSdkVersion 23 // 表示基本哪个Android版本开发
        versionCode 1 // APP应用内部版本名称
        versionName "1.0" // APP应用的版本名称
    }
    buildTypes{
        release{ // 构建类型
            minifyEnabled false // 是否启用混淆
            proguardFiles getDefaultPraguardFile('proguard-andrcid.txt'), 'proguard-rules.pro' // 配置混淆文件
        }
    }
}
// 配置第三方依赖
dependencies{
   implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

android{}是Android Gradle插件提供的一个扩展类型,可以让我们自定义Android Gradle工程。defaultConfig{}是默认的配置,是一个ProductFlavor(构建渠道),ProductFlavor允许我们根据不同的情况同时生成不同的APK包。buildTypes{}是一个NamedDomainObjectContainer类型,是一个域对象,可以在buildTypes{}里新增任意多个我们需要构建的类型,比如debug类型。

NamedDomainObjectContainer具体可以参考-NamedDomainObjectContainer详解

3.3.3 多渠道构建

由于发布或者推广APP的渠道不同,就造成了Android APP可能会有很多个,所以需要针对不同的渠道做不同的处理。
在Android Gradle中,定义了一个叫Build Variant(构建变体/构建产物)的概念,一个构建变体(Build Variant)=构建类型(Build Type)+构建渠道(Product Flavor),下面举个例子:

  • Build Type有release、debug两种构建类型
  • Product Flavor有baidu、google两种构建渠道
  • Build Variant有baiduRelease、baiduDebug、googleRelease、googleDebug四种构件产物

配置好发布渠道后,Android Gradle插件就会生成很多task,比如assembleBaidu,assembleRelease,assembleBaiduRelease

Gradle中一个原子性的操作叫做task,简单理解为task是Gradle脚本中的最小可执行单元。

  1. assembleBaidu:运行后会生成baidu渠道的release和debug包
  2. assembleRelease:运行后会生成所有渠道的release包
  3. assembleBaiduRelease:运行后只会生成baidu的release包

4. Android Studio Gradle插件构建流程

4.1 Gradle生命周期

image
  1. Initialization(初始化阶段):Gradle支持单项目和多项目构建。在初始化阶段,Gradle确定将要参与构建的项目,并为每个项目创建一个Project对象。通俗的说就是执行上述settings.gradle文件。
  2. Configuration(配置阶段):在此阶段,解析每个Project中的build.gradle文件,并生成将要执行的task。
  3. Execution(执行阶段):执行 task,进行主要的构建工作

4.2 APK构建流程

构建流程涉及许多将项目转换成 Android 应用软件包 (APK)的工具和流程,具体如下图所示:

image

Android 应用模块的构建流程通常按照以下步骤执行:

  1. 编译器将您的源代码转换成 DEX 文件(Dalvik 可执行文件,其中包括在 Android 设备上运行的字节码),并将其他所有内容转换成编译后的资源
  2. APK 打包器将 DEX 文件和编译后的资源合并到一个 APK 中。不过,在将应用安装并部署到 Android 设备之前,必须先为 APK 签名。
  3. APK 打包器使用调试或发布密钥库为 APK 签名
  1. 在生成最终 APK 之前,打包器会使用 zipalign 工具对应用进行优化,以减少其在设备上运行时所占用的内存。

构建流程结束时,将获得应用的调试版 APK 或发布版 APK,以用于部署、测试或发布给外部用户。

以上摘自Android开发者指南

行文至此,本文已大概理清Gradle的基本概念,以及其在Android Studio中的工作流程,但Android Studio中Gradle的工作具体细节还未解释,如点击Run图标背后的Gradle的具体工作流程是什么?这些会在后续博客中继续分析。

作者:Hengtao24
链接:https://www.jianshu.com/p/63e78a6c6e9d

上一篇下一篇

猜你喜欢

热点阅读