美文网首页Android开发经验谈Android开发
Android中用到的Gradle原理是什么?

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

作者: Android进阶小麦 | 来源:发表于2020-05-30 21:25 被阅读0次

    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 插件种类

    • 二进制插件:实现了org.gradle.api.Plugin接口的插件,拥有plugin id,这个 id 是插件全局唯一的标识或名称
    • 脚本插件:严格上只是一个脚本,即自定义的以 .gradle 为后缀的脚本文件,可以来自本地或网络

    3.2.2 插件用法

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

    • 二进制插件

    id式:apply plugin:'plugin id'

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

    简写式:apply plugin:JavaPlugin

    • 脚本插件apply from:'version.gradle'
    • 第三方发布插件apply plugin:'com.android.application'

    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脚本中的最小可执行单元。

    • assemble开头的Task负责生成构件产物(Apk)
    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 签名
    • a. 如果构建的是调试版应用(即专用于测试和分析的应用),则打包器会使用调试密钥库为应用签名。Android Studio 会自动使用调试密钥库配置新项目。
    • b. 如果构建的是打算对外发布的发布版应用,则打包器会使用发布密钥库为应用签名
    1. 在生成最终 APK 之前,打包器会使用 zipalign 工具对应用进行优化,以减少其在设备上运行时所占用的内存。

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

    以上摘自Android开发者指南

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

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

    相关文章

      网友评论

        本文标题:Android中用到的Gradle原理是什么?

        本文链接:https://www.haomeiwen.com/subject/fbzhzhtx.html