zoukankan      html  css  js  c++  java
  • Android Gradle 自定义Task 详解

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/76408024
    本文出自【赵彦军的博客】

    一:Gradle 是什么

    • Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建工具。
    • 它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。面向Java应用为主。
    • 当前其支持的语言限于Java、Groovy、Kotlin和Scala,计划未来将支持更多的语言。基于 groovy 脚本构建,其 build 脚本使用 groovy 语言编写。

    关于 gradle 相关运用,可以移步 :Android Gradle使用总结

    二:groovy 是什么

    Groovy是一种动态语言,它和Java类似(算是Java的升级版,但是又具备脚本语言的特点),都在Java虚拟机中运行。当运行Groovy脚本时它会先被编译成Java类字节码,然后通过JVM虚拟机执行这个Java字节码类。

    关于 groovy 相关知识,移步到这里:Groovy 使用完全解析

    三:Gradle 的 Project 和 Tasks

    每次构建(build)至少由一个project构成,一个project 由一到多个task构成。每个task代表了构建过程当中的一个原子性操作,比如编译,打包,生成javadoc,发布等等这些操作。

    gradle : 一个 project 包含多个 task,一个 task 包含多个 Action

    project 
                      -- task1 (Action1、Action2...)
                      -- task2 (Action1、Action2...)
                      -- ... 
    

    四:自定义 Task

    • 格式:
     task 任务的名字 {
        //do some things
     }
    
    
    • 例子

    build.gradle

    //定义 task , 名字 hello 
    task hello{
        println "hello world"
    }
    
    //定义 task,名字 hello 
    task(hello2){
        println "hello world2"
    }
    
    //定义 task,名字 hello3 
    task ('hello3'){
        println "hello world3"
    }
    
    
    
    • 在终端运行 gradle 命令
    
    //执行 hello task
    gradlew hello
    
    //执行 hello2 task
    gradlew hello2
    
    //执行 hello3 task
    gradlew hello3
    
    

    五:创建Action

    在上面的举例中,是一个非正式的 task , 说非正式是因为创建的 task 里面没有 action 。task 本质上又是由一组被顺序执行的 Action 对象构成,Action其实是一段代码块,类似于Java中的方法。

    创建 Action 相关 API

     //在Action 队列头部添加Action
     Task doFirst(Action<? super Task> action);
     Task doFirst(Closure action);
    
     //在Action 队列尾部添加Action
     Task doLast(Action<? super Task> action);
     Task doLast(Closure action);
        
     //已经过时了,建议用 doLast 代替
     Task leftShift(Closure action);
    
     //删除所有的Action
     Task deleteAllActions();
    
    

    小例子

    build.gradle

    //创建一个名字为hello的 task 
    task hello {
    
        //创建一个 Action , 添加到 Action 列表的头部
       doFirst(new Action<Task>() {
           @Override
           void execute(Task task) {
               println "action1++++++++++"
           }
       })
    
        //创建一个 Action , 添加到 Action 列表的头部
        doFirst {
            println "action2++++++++++"
        }
    
    }
    
    

    在 Action 列表中添加了 两个 Action , Action 列表如下图所示:

    这里写图片描述

    运行 hello task : gradle hello

    运行结果:

    
    action2++++++++++
    action1++++++++++
    
    

    leftShift 说明

    leftShift 的作用和 doLast 一样,在action 列表尾部添加一个Action,只不过现在过时了,官方建议用 doLast 代替。下面举个小例子:

    build.gradle

    task hello {
        //在 Action 列表尾部添加一个 Action 
        leftShift {
            println "+++++"
        }
    }
    
    

    leftShift 还有一种简洁写法,用 << 代替, 如下所示:

    build.gradle

    task hello <<{
        //在 Action 列表尾部添加一个 Action 
        println "+++++"
    }
    
    

    那么问题来了,task 中的 Action 在什么时候执行?

    六:Gradle 生命周期

    1.初始化阶段

    会去读取根工程中 setting.gradle 中的 include 信息,决定有哪几个工程加入构建,创建 project 实例,比如下面有三个工程: include ':app', ':lib1', ':lib2 。

    2.配置阶段

    会去执行所有工程的 build.gradle 脚本,配置 project对象,一个对象由多个任务组成,
    此阶段也会去创建、配置task及相关信息。

    3.运行阶段

    根据gradle命令传递过来的task名称,执行相关依赖任务。Task 的 Action 会在这个阶段执行。

    七:创建 Task 的另外一种方式

    在上面讲解了创建 task 的基本方式,其实 gradle api 给我们提供了其他的方式创建 task ,下面讲解其他两种方式。

    • tasks

    build.gradle

    
    //创建 hello2 task
    tasks.create("hello2"){
        doFirst {
            println "hello2+++++"
        }
    }
    
    • 自定义 DefaultTask 子类
    class MyTask extends DefaultTask {
        
        @TaskAction
        void action(){
            println "action1+++++"
        }
    }
    
    //创建 hello3 task
    task hello3 (type: MyTask){
        doLast{
           println "action2+++++"
        }
    }
    
    

    运行 hello3 task: gradlew hello3

    输出

    action1+++++
    action2+++++

    八: Task 依赖

    1、dependsOn

    build.gradle

    task task1 << {
        println "我是task1----"
    }
    
    task task2 << {
        println "我是task2----"
    }
    
    //task2 依赖 task1, 执行task2之前先执行task1
    task2.dependsOn task1
    
    

    执行 task2

    gradlew task2

    执行效果

    我是task1----
    我是task2----

    2、mustRunAfter

    两个 task 依赖

    
    task task1 << {
        println "我是task1----"
    }
    
    task task2 << {
        println "我是task2----"
    }
    
    //task2 运行之前先运行task1
    task2.mustRunAfter task1
    
    
    • 执行 task1 : gradlew task1

    我是task1----

    • 执行 task2 : gradlew task2

    我是task2----

    • 同时执行 task1、task2 : gradlew task1 task2

    我是task1----
    我是task2----

    三个 task 相互依赖

    build.gradle

    task task1 << {
        println "我是task1----"
    }
    
    task task2 << {
        println "我是task2----"
    }
    
    task task3 << {
        println "我是task3----"
    }
    
    task2.mustRunAfter task1
    task3.mustRunAfter task1
    
    
    • 执行 gradlew task1 task2 task3

    我是task1----
    我是task2----
    我是task3----

    • 执行 gradlew task1 task3 task2

    我是task1----
    我是task3----
    我是task1----

    在出现语法矛盾的情况下,依赖关系形成闭环,编译器会报错

    task1.mustRunAfter task2
    task2.mustRunAfter task1
    

    3、shouldRunAfter

    形成依赖关系可有可无。

    build.gradle

    task task1 << {
        println "我是task1----"
    }
    
    task task2 << {
        println "我是task2----"
    }
    
    task1.shouldRunAfter task2
    
    

    运行: gradlew task1 task2

    我是task2----
    我是task1----

    在出现语法矛盾的情况下,依赖关系形成闭环,会自动打破闭环。不会报错

    九:系统默认 task

    gradle 默认提供了很多 task 给我们使用,比如 copy、delete

    1、copy

    build.gradle

    
    task 任务的名字 (type: Copy) {
        //action 
    }
    
    
    • Api 介绍
    
    //数据源目录,多个目录
    public AbstractCopyTask from(Object... sourcePaths)  
    
    //目标目录,单一
    public AbstractCopyTask into(Object destDir) 
    
    //过滤文件 包含
    public AbstractCopyTask include(String... includes)
    
    //过滤文件 排除
    public AbstractCopyTask exclude(String... excludes)
    
    //重新命名,老名字 新名字
    public AbstractCopyTask rename(String sourceRegEx, String replaceWith)
    
    //删除文件 Project 接口
    boolean delete(Object... paths);
    
    

    小例子:

    • 复制图片:单一数据源
    
    task copyImage(type: Copy) {
        from 'C:\Users\yiba_zyj\Desktop\gradle\copy'
        into 'C:\Users\yiba_zyj\Desktop'
    }
    
    
    • 复制图片:多个数据源
    
    task copyImage(type: Copy) {
        from 'C:\Users\yiba_zyj\Desktop\gradle\copy' , 
             'C:\Users\yiba_zyj\Desktop\gradle\copy'
        
        into 'C:\Users\yiba_zyj\Desktop'
    }
    
    
    • 复制图片:过滤文件

    只会复制后缀为 .jpg 的文件

    
    task copyImage(type: Copy) {
        from 'C:\Users\yiba_zyj\Desktop\gradle\copy'
        into 'C:\Users\yiba_zyj\Desktop'
        include "*.jpg" 
    }
    
    
    • 复制文件:过滤文件,重命名
    
    task copyImage(type: Copy) {
        from 'C:\Users\yiba_zyj\Desktop\gradle\copy'
        into 'C:\Users\yiba_zyj\Desktop'
        include "*.jpg"
        exclude "image1.jpg"
        rename("image2.jpg","123.jpg")
    }
    
    

    文件覆盖规则

    相同文件覆盖

    Copy 类的继承图

    Copy (类)
       - AbstractCopyTask (抽象类)  (from、 into、 include、rename)
          -ConventionTask(抽象类)
           - DefaultTask (类)
            - AbstractTask (抽象类)
               - TaskInternal (接口)
                - Task(接口)        
                  -Comparable<Task>, ExtensionAware(接口)
                    -Project(接口)    (delete 方法)
    
    

    2、Delete

    • 删除 Android 更目录的aaa 文件

    build.gradle

    
    task deleteFile(type: Delete) {
        //删除Android 更目录的aaa 文件
        delete '../aaa'  
    }
    
    
    • 删除桌面上的文件

    build.gradle

    
    task deleteFile(type: Delete) {
        //删除系统桌面 delete 
        delete "C:\Users\yiba_zyj\Desktop\gradle\delete"
    }
    
    

    十:小技巧

    1、自定义 task 的名字用驼峰命名法

    build.gradle

    
    task deleteFile{
        //do some things
    }
    
    

    运行

    gradlew dF 等价 gradlew deleteFile

    打包时候运行 gradlew assembleRelease ,可以简写成 gradlew aR

    2、常见的 gradlew 命令

    查看项目所有默认自带的 task,不包括自定义 task

    gradlew tasks

    查看所有 task (默认 task + 自定义task)

    gradlew tasks --all

    查看某个 task 的相关信息,这些结果包含了任务的路径、类型以及描述信息等

    gradlew help --task taskName

    查看 gradle 版本

    gradlew -version

    3、给task 添加描述 description

    
    task task1 << {
        description = "这是一段描述信息"
        println "我是task1----"
    }
    
    

    十一:Gradle 环境变量配置

    在上面的介绍中,运行 task 的方式是用 gradlew , 那我们怎么用 gradle 。如果在终端运行 gradle 就会提示 gradle 不是内部或外部命令,也不是可运行的程序或批处理文件。

    
    'gradle' 不是内部或外部命令,也不是可运行的程序或批处理文件。
    
    

    官网下载:http://services.gradle.org/distributions/

    下载完成后,我将压缩包解压放在 d 盘的 soft 目录中。
    环境变量

    • GRADLE_HOME

    D:softgradle-4.3-all

    • Path

    D:softgradle-4.3-allgradle-4.3in

    参考资料

    1、Android Gradle 必备实用技巧

    2、Android Gradle使用总结

    3、Groovy 使用完全解析

    4、深入理解 Android Gradle 详解


    个人微信号:zhaoyanjun125 , 欢迎关注

  • 相关阅读:
    web服务器iis安全设置
    Log explorer for sql server
    C#将image中的显示的图片转换成二进制
    .Net平台开发的技术规范与实践精华总结
    .net面试题整理
    Javascript 刷新框架及页面的方法总集
    WEB程序代码优化入手的几方面
    用js控制网页播放器
    SQL Server2000中死锁经验总结
    专家谈CSS设计
  • 原文地址:https://www.cnblogs.com/zhaoyanjun/p/7988965.html
Copyright © 2011-2022 走看看