android中gradle的作用,Gradle 之 Android 中的应用

在上一篇文章中 Gradle 之语言基础 Groovy 主要介绍了 Groovy 的基础语法(如果没有 Groovy 的基础,建议先看看上篇文章,如果可以动手敲一下里面的示例代码就更好不过了),也是为本篇文章打基础的。

本篇文章主要介绍 Gradle 在 Android 中的应用(Android DSL 和 Gradle DSL),也是通过一些示例来介绍和理解,主要分为以下一些内容,示例代码都在 GradleForAndroid

一. Gradle 构建生命周期

一个 Gradle 的构建通常有如下三个阶段

初始化:项目 Project 实例会在该阶段被创建。如果一个项目中包含有多个模块,并且每一个模块都有其对应的 build.gradle 文件,就会为每一个模块都创建一个对应的 Project 实例

配置:执行各个模块下的 build.gradle 脚本,为 Project实例创建和配置 Task,构造 Task 任务依赖关系图以便在执行阶段按照依赖关系执行 Task

执行:在这个阶段将会决定执行哪个 Task,哪个 Task 被执行取决于开始该次构建的参数配置和该 Gradle 文件的当前目录

在创建完成一个新的 Android 应用项目之后,一般情况下, .gradle 文件的目录结构如下所示:

GradleForAndroid

|---- build.gradle

|---- setting.gradle

\---- app

\---- build.gradle

其中,两个文件 build.gradle 和 setting.gradle 位于项目的根目录下,还有一个 build.gradle 位于 \app\ 目录下。\build.gradle 是顶层构建文件,\app\build.gradle 是模块构建文件。

我们以上面这个新创建的项目来学习 Gradle 的构建生命周期

1.1 初始化

在初始化阶段,会创建一个 Setting 对象,对应着 setting.gradle 文件,

Setting 对象的一个主要作用就是声明哪些模块将会参与到构建中去,Setting 文档(Gradle API 5.0)

在新建的项目中,setting.gradle 文件一般会默认包含一行内容,如下所示

include ':app'

上面这一行,其实是一行 groovy 代码的简写,对应的是 Setting#include(String[] projectPaths) 方法,表示 :app 模块将会参与到构建中去。

如果我们创建一个 library 库,setting.gradle 将会变为如下所示,表示 :app 和 :library 两个模块将会参与到构建中

include ':app', ':library'

setting.gradle 脚本文件可以中读取一些只可读的配置信息,这些配置信息的来源可以有如下三个:

可以在本工程的 gradle.properties 文件中定义配置信息

也可以在系统的 gradle.properties 文件中定义配置信息,系统的 gradle.properties 位于 user's .gradle 目录下

还可以通过 -P 命令参数指定配置信息,比如 ./gradlew clean -P cmd='Hello from commandLine' 便在执行 clean task 的时候,指定了 cmd='Hello from commandLine' 配置信息

上面讲到,一个 setting.gradle 文件对应着一个 Setting 对象,Setting 对象包含的方法如下图所示

8b74e9cb5f08

Setting.png

例如有如下代码

include ':app', ':library'

println propertiesFile

println DEFAULT_SETTINGS_FILE

println getRootProject().name

println getRootProject().path

getGradle().addBuildListener(new BuildListener() {

@Override

void buildStarted(Gradle gradle) {

println 'buildStarted'

}

@Override

void settingsEvaluated(Settings settings) {

println "settingsEvaluated"

}

@Override

void projectsLoaded(Gradle gradle) {

println 'projectsLoaded'

}

@Override

void projectsEvaluated(Gradle gradle) {

println 'projectsEvaluated'

}

@Override

void buildFinished(BuildResult result) {

println 'buildFinished'

}

})

其输出是:

Hello from gradle.properties

settings.gradle

GradleForAndroid

:

settingsEvaluated

projectsLoaded

projectsEvaluated

BUILD SUCCESSFUL in 0s

3 actionable tasks: 3 executed

buildFinished

1.2 配置

在配置阶段,会执行所有的 build.gradle,包括项目根目录下的 build.gradle 和各个 module 下的 build.gradle

在执行 build.gradle 的时候,会为每个 build.gradle 创建一个对应的 Project 对象,Project 文档(Gradle API 5.0)

配置阶段会执行 build.gradle 里面的所有代码和 Task 里面的配置代码,比如下面的 printProperties Task,只执行了 doLast{} 之外的代码,doLast{} 之外的代码是 Task 的配置代码

配置执行完成之后,会根据各个 Task 的依赖关系生成一个有向无环图,可以通过Gradle对象的getTaskGraph方法访问,对应的类为TaskExecutionGraph

在执行所有的 Gradle Task 之前,都会执行 初始化阶段 和 配置阶段 的代码

比如有如下代码

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

println "/build.gradle 开始配置"

buildscript {

println "/build.gradle buildscript 开始配置"

ext.kotlin_version = '1.2.71'

repositories {

google()

jcenter()

}

dependencies {

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

classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

// NOTE: Do not place your application dependencies here; they belong

// in the individual module build.gradle files

}

println "/build.gradle buildscript 结束配置"

}

allprojects {

println "/build.gradle allprojects 开始配置"

repositories {

google()

jcenter()

}

println "/build.gradle allprojects 结束配置"

}

task clean(type: Delete) {

delete rootProject.buildDir

}

ext {

local = 'Hello from build.gradle'

}

task printProperties {

println "/build.gradle task printProperties 开始配置"

println '/build.gradle task printProperties'

println "/build.gradle task printProperties 结束配置"

doLast {

println local

println propertiesFile

if (project.hasProperty('cmd')) {

println cmd

}

}

}

println "/build.gradle 结束配置"

在 Terminal 里面执行 ./gradlew clean 会有如下输出

Hello from gradle.properties

settings.gradle

GradleForAndroid

:

settingsEvaluated

projectsLoaded

// 配置阶段,执行 /build.gradle 里面的代码

> Configure project :

/build.gradle buildscript 开始配置

/build.gradle buildscript 结束配置

/build.gradle 开始配置

/build.gradle allprojects 开始配置

/build.gradle allprojects 结束配置

/build.gradle allprojects 开始配置

/build.gradle allprojects 结束配置

/build.gradle allprojects 开始配置

/build.gradle allprojects 结束配置

/build.gradle task printProperties 开始配置

/build.gradle task printProperties

/build.gradle task printProperties 结束配置

/build.gradle 结束配置

projectsEvaluated

BUILD SUCCESSFUL in 0s

3 actionable tasks: 3 executed

buildFinished

1.3 执行

执行阶段就是指执行某个具体的任务 Task。说道 Task,我想大家应该比较熟悉,在 Android 项目中依赖了 Android Gradle 插件以后,会有许多自带的 Task,比如常用的 clean、assemble 等,而且大家更应该掌握的是如何自定义 Task,关于 Task 会单独抽一节来讲述。

二. 自定义 Task

任务 Task 代表了在构建过程中的一个单原子性的动作,比如:编程生成 .class 文件或者生成 javadoc 等.

每一个 task 都是属于某一个 Project 对象的,每一个 task 都有自己的名字,在 project 中 task 的名字是唯一的,如果在整个项目 projects 范围内需要指定某个 task 的话,也需要指定 project 的名字,project 和 task 的名字中间使用 : 相连接,比如:./gradlew :app:clean

创建 Task 对象的方法有以下几种

// 通过 TaskContainer.create(String) 创建 `Task`

getTasks().create('helloTask') {

doLast {

println 'create Task by TaskContainer'

}

}

task helloTask1 {

doLast {

println 'create Task by task(String name)'

}

}

class HelloTask extends DefaultTask {

def message = 'create Task by extends DefaultTask'

@TaskAction

def hello() {

println message

}

}

// 通过 type 参数可以指定该 task 的父类,默认的父类是 DefaultTask

task helloTask2(type: HelloTask)

一个 Task 是由一系列的 Action 组成的,当一个 Task 执行的时候就是按照一定的顺序执行这些 Action,可以有以下两种方式向 Task 中添加 Action

通过闭包 Closure 的方式添加 Action

class HelloTask extends DefaultTask {

def message = 'create Task by extends DefaultTask'

@TaskAction

def hello() {

println message

}

}

task helloTask2(type: HelloTask) {

doFirst {

println 'helloTask2 doFirst'

}

doLast {

println 'helloTask2 doLast'

}

}

直接添加 Action 实例对象

def taskDef = task helloTask3(type: HelloTask)

taskDef.doFirst(new Action() {

@Override

void execute(Task task) {

println 'helloTask3 Action execute doFirst'

}

})

taskDef.doLast(new Action() {

@Override

void execute(Task task) {

println 'helloTask3 Action execute doLast'

}

})

Task 依赖关系 & Task 执行顺序

在 Task 中有两个很重要的概念 dependsOn 和 mustRunAfter。dependsOn 用于声明两个 Task 对象之间的依赖关系,mustRunAfter 用于声明一个 Task 必须在另一个 Task 之后运行,虽然感觉差不多,但是实际上还是有区别的

helloTaskB.dependsOn(helloTaskA) 中,可以单独运行 helloTaskA,但是运行 helloTaskB 的时候会触发 helloTaskA 的执行

helloTaskC.mustRunAfter(helloTaskA)中,helloTaskA 和 helloTaskC 都是可以单独运行的,但是当 helloTaskC 和 helloTaskA 同时运行时,helloTaskC 一定会在 helloTaskA 之后运行

task helloTaskA {

doFirst {

println 'helloTaskA doFirst'

}

}

task helloTaskB {

doFirst {

println 'helloTaskB doFirst'

}

}

helloTaskB.dependsOn(helloTaskA)

task helloTaskC {

doFirst {

println 'helloTaskC doFirst'

}

}

helloTaskC.mustRunAfter(helloTaskA)

Android 中使用自定义 Task

在 Gradle 构建的时候,需要将自定义的 Task 添加到构建过程中时,需要把握好添加自定义 Task 的时机与位置

下面一幅图清晰地展示了 Gradle 构建过程中一些关键的回调,可以在下面一些回调中添加自定义 Task

在 project 对象中,可以通过 gradle 对象得到 TaskExecutionGraph 的实例对象,也可以通过 TaskExecutionGraph 实例对象一些关键回调添加自定义的 Task。比如下面这个例子,就是在 TaskExecutionGraph 实例对象准备好之后,弹出一个 dialog 用于输入 storePass 和 keyPass,然后将 storePass 和 keyPass 设置到 android.signingConfigs 中

apply plugin: 'com.android.application'

import groovy.swing.SwingBuilder

//......

gradle.taskGraph.whenReady { taskGraph ->

if (taskGraph.hasTask(':app:assembleRelease')) {

def storePass = ''

def keyPass = ''

if (System.console() == null) {

System.setProperty('java.awt.headless', 'false')

new SwingBuilder().edt {

dialog(modal: true, title: 'Enter password', alwaysOnTop: true, resizable: false, locationRelativeTo: null, pack: true, show: true) {

vbox { // Put everything below each other

label(text: "Please enter store passphrase:")

def input1 = passwordField()

label(text: "Please enter key passphrase:")

def input2 = passwordField()

button(defaultButton: true, text: 'OK', actionPerformed: {

storePass = input1.password;

keyPass = input2.password;

dispose();

})

}

}

}

} else {

storePass = System.console().readPassword("\nPlease enter store passphrase: ")

keyPass = System.console().readPassword("\nPlease enter key passphrase: ")

}

if (storePass.size() <= 0 || keyPass.size() <= 0) {

throw new InvalidUserDataException("You must enter the passwords to proceed.")

}

storePass = new String(storePass)

keyPass = new String(keyPass)

android.signingConfigs.release.storePassword = storePass

android.signingConfigs.release.keyPassword = keyPass

}

}

如下图所示 TaskExecutionGraph 的方法结构如下图所示,都是非常实用方便的方法

8b74e9cb5f08

TaskExecutionGraph.png

三. Android DSL & Gradle DSL

3.1 Android DSL

Android DSL 是 Gradle 的一个 Android 插件,其实在使用 Android Studio 开发的时候经常会和 Android DSL 打交道,比如下面 android{ } 闭包 里面的内容都是 Android DSL

apply plugin: 'com.android.application'

import groovy.swing.SwingBuilder

android {

compileSdkVersion 27

defaultConfig {

applicationId "com.lijiankun24.gradleforandroid"

minSdkVersion 15

targetSdkVersion 27

// ......

}

buildTypes {

// ......

}

signingConfigs {

// ......

}

}

至于里面都有哪些 API,可以去 Android DSL 文档 查看,也可以去 GitHub 上面搜 android-gradle-dsl

3.2 Gradle DSL

Gradle DSL 在上面介绍 Gradle 生命周期和自定义 Task 的时候已经介绍过了,比如上面介绍的 Setting 和 TaskExecutionGraph 都是 Gradle DSL 中的类,其他的类和方法等 API 可以去 Gradle DSL 文档 查看,或者可以在 Android Studio 中像查看 Android SDK 源码一样去查看 Gradle DSL 的源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/530826.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自己写的android apk反编译,获取Android自己写好了的apk以及反编译

今天&#xff0c;我们先说一下&#xff0c;获取Android自带的apk以及反编译它们来学习Android工程师是怎样写的&#xff0c;今天我们就以拿到Android自带的短信管理器的apk为例子你可能有疑问&#xff0c;为什么要那么麻烦&#xff0c;从系统来拿&#xff0c;还要反编译&#x…

一加7pro系统更新android10,一加OnePlus7T Pro官方安卓10.0稳定版出厂系统固件升级更新包...

咱们的这个一加OnePlus7T Pro手机的最新稳定版系统包也是在这里来分享一下了&#xff0c;这个稳定版本的系统包是安卓10稳定版的&#xff0c;也是第一个版本的&#xff0c;系统包大小是3.2G&#xff0c;系统方面主要是全新的UI设计&#xff0c;轻快流畅操作体验&#xff0c;更多…

5元素升级android6,升级你的app以支持高长宽比的新旗舰

为了呈现更好的视觉效果&#xff0c;许多安卓OEM厂商都开始采用超大屏幕。三星刚刚发布了自己的新旗舰Samsung Galaxy S8&#xff0c;长宽比达到18.5:9。今年早些时候的全球移动大会上LG也亮相了 LG G6&#xff0c;屏幕长宽比达到了18:9。(左) maximum aspect ratio为16:9的app…

CCS太阳光准直系统使用积分球均匀光源

CCS太阳光准直系统的应用范围广泛&#xff0c;包括太阳光辐射测量、光学遥感仪器研制与标定、均匀光源的推广使用等方面。通过使用CCS太阳光准直系统&#xff0c;可以准确地模拟太阳光&#xff0c;并对各种光学仪器进行校准和标定&#xff0c;从而提高测量精度和稳定性。 CCS太…

js怎么制作html的主题,用HTML和CSS以及JS制作简单的网页菜单界面的代码

写ABROAD项目用到了标签这个东东&#xff0c;其实标签在WEB上到处可见&#xff0c;图中就依次显示了DCC文章发布器、ABROAD后台添加数据、百度图片搜索、sf发布博客文章时贴标签的样式——标签就像浏览器里原生的checkbox一样&#xff0c;不过checkbox实在太丑了&#xff0c;就…

哔哩网站登录界面html代码,仿哔哩哔哩网页模板设计

【实例简介】【实例截图】【核心代码】bilibili├── Home.html├── Login.html├── Register.html├── css│ ├── bootstrap.min.css│ └── css.css├── forget the password.html├── img│ ├── 001.png│ ├── 002.png│ ├── 003.png│ …

2021高考成绩查询大连,2021年大连高考各高中成绩及本科升学率数据排名及分析...

一、大连高考各高中成绩及本科升学率数据2020年辽宁省普通高等学校招生文化课录取控制分数线普通类 文史特殊类型招生控制分数线&#xff1a;567分本科控制分数线&#xff1a;472分专科(高职、提前专科)控制分数线&#xff1a;150分普通类 理工特殊类型招生控制分数线&#x…

编写了html怎么测试,如何将测试结果写入HTMLTestRunner生成的报告标题中

HTMLTestRunner生成测试报告时&#xff0c;报告的标题在运行前就已经写死在代码了&#xff0c;假如我现在需要在执行完毕后&#xff0c;根据执行结果&#xff0c;把执行的状态写在标题里面&#xff0c;类似的效果如图&#xff1a;标题如果有一条执行错误的&#xff0c;就在后面…

编码 data text html c,谁说前端不需要懂二进制

作者&#xff1a;全栈成长之路 公号 / 山月行作为一名前端&#xff0c;在工作中也会遇到很多有关二进制处理的需求&#xff0c;如 EXCEL 表格的导出&#xff0c;PDF 的生成&#xff0c;多个文件的打包&#xff0c;音频的处理。从前后端整体上来说前端代表 UI 层&#xff0c;它的…

计算机联用测定无机盐溶解热测试题,计算机联用测定无机盐溶解热

计算机联用测定无机盐溶解热计算机联用测定无机盐溶解热一 实验目的1. 用量热计测定KCl的积分溶解热。2. 掌握量热实验中温差校正方法以及与计算机联用测量溶解过程动态曲线的方法。二 实验原理盐类的溶解过程通常包含着两个同时进行的过程&#xff1a;晶格的破坏和离子的溶剂化…

初中计算机考试用什么软件,初中信息技术《PowerPoint软件》考过啥

教师资格考试的试题中&#xff0c;不会缺少办公软件的身影&#xff0c;而办公软件作为最重要的文字处理工具&#xff0c;都考过哪些题目呢?该如何学习呢?中公教师给您指引方向。一、考题集锦1.PowerPoint中&#xff0c;为了让海龟按图1所示路线运动&#xff0c;应采用的方法是…

达内计算机毕业好找工作吗,大学生学什么好找工作 转行IT行业需要多久

6月毕业季&#xff0c;工作好找吗&#xff1f;9月招聘季&#xff0c;求职顺利吗&#xff1f;一直以来工作难找、人难招究竟难在哪&#xff1f;而另一边&#xff0c;企业求贤若渴&#xff0c;主动抢夺优秀人才&#xff01;却有很多毕业生抱怨求职难&#xff0c;找不到理想的工作…

ajax数据交互代码,Django中使用jquery的ajax进行数据交互的实例代码

jquery框架中提供了$.ajax、$.get、$.post方法&#xff0c;用于进行异步交互&#xff0c;由于Django中默认使用CSRF约束&#xff0c;推荐使用$.get示例&#xff1a;实现省市区的选择最终实现效果如图&#xff1a;将jquery文件拷贝到static/js/目录下打开booktest/views.py文件&…

MySQL 入门教程:全网最全,MySQL 增删改查高级命令硬核总结

文章目录前言一、连接到 MySQL 数据库1.1、连接到本机上的 MySQL1.2、连接到远程主机上的 MySQL二、退出 MySQL 命令三、修改 MySQL 密码3.1、先给 root 用户加个密码 ab123.2、再将 root 用户的密码改为 djg345四、增加新用户4.1、增加一个可以在任何主机上登录用户 test1&…

网站设计好怎么上传到服务器的,虚拟主机上传到网站的几个步骤

虚拟主机怎么上传到网站?站长们可以利用专业的软件协助自己上传&#xff0c;比如专业的ftp软件&#xff0c;具备支持续点相传&#xff0c;上传&#xff0c;以及下载目录等等&#xff0c;不会将限制过长的网站剔除&#xff0c;还可以下载列队&#xff0c;可以长传到本地&#x…

数据库管理工具:全网最全,MySQL 数据库图形化管理界面应用 Navicat Premium 使用教程

文章目录前言一、Navicat 下载和安装1.1、Navicat 下载1.2、Navicat 安装和启动二、创建数据库连接2.1、连接本地数据库2.2、连接远程数据库三、对数据库的“增删改查”功能操作3.1、对数据库的基本操作3.1.1、新建数据库3.1.2、删除数据库3.1.3、修改数据库3.1.4、查询数据库3…

电脑无线网络与服务器共享,图文详解win7笔记本如何实现内置无线局域网卡共享...

图文详解win7笔记本如何实现内置无线局域网卡共享&#xff1a;windows7集合了众多优点于一身&#xff0c;带来了空前的操作体验&#xff0c;同时还吸取了苹果Mac OS X系统的特色&#xff0c;因此很多用户在新购置笔记本电脑的时候都预装了win7系统&#xff0c;而且现在市面上出…

数据库深度剖析:Oracle、Microsoft SQL Server、MySQL 三者有何区别?

文章目录前言一、Oracle 数据库1.1、支撑平台范围广1.2、Oracle 在兼容性、可移植性、可联结性、高生产率上、开放性也存在优点1.3、Oracle 价格是比较昂贵的二、Microsoft SQL Server 数据库2.1、可伸缩性好、与相关软件集成程度高2.2、拥有良好的 ODBC 接口2.3、基于微软&…

MySQL 完全卸载:教你如何完全卸载掉本地令人头大的 MySQL 数据库

文章目录前言一、控制面板卸载 MySQL二、删除 MySQL 数据库安装文件夹三、打开注册表编辑器四、删除残留注册表文件五、删除系统盘残留数据文件总结前言 如果我们 MySQL 数据库密码遗忘需要重新安装 MySQL 数据库时&#xff0c;就需要先卸载掉本地的文件。而 MySQL 并不是像其他…

MySQL 外码约束原理:如何解决数据库添加数据时产生的外码(外键)约束?

文章目录前言一、插入新数据时报错外键约束&#xff1f;二、对于出错 SQL 语句的分析三、对于外码约束的分析四、如何处理外键约束&#xff1f;总结前言 我们在使用 MySQL 数据库时&#xff0c;添加数据如果设计不合理很容易出现外码约束的情况&#xff0c;为什么会产生这样的问…