reference to : http://blog.csdn.net/lzyzsd/article/details/46935405

原文链接

我注意到我在使用Gradle的时候遇到的大多数问题都是和task的执行顺序有关的。很明显如果我的构建会工作的更好如果我的task都是在正确的时候执行。下面我们就深入了解一下如何更改task的执行顺序。

dependsOn

我认为最直接的方式来说明的你task的执行时依赖别的task的方法就是使用dependsOn方法。
比如下面的场景,已经存在task A,我们要添加一个task B,它的执行必须要在A执行完之后:

这是一个很简单的场景,假定A和B的定义如下:

  1. task A << {println 'Hello from A'}
  2. task B << {println 'Hello from B'}

只需要简单的调用B.dependsOn A,就可以了。
这意味着,只要我执行task B,task A都会先执行。

  1. paveldudka$ gradle B
  2. :A
  3. Hello from A
  4. :B
  5. Hello from B

另外,你也可以在task的配置区中来声明它的依赖:

  1. task A << {println 'Hello from A'}
  2. task B {
  3. dependsOn A
  4. doLast {
  5. println 'Hello from B'
  6. }
  7. }

如果我们想要在已经存在的task依赖中插入我们的task该怎么做呢?


过程和刚才类似。假定已经存在如下的task依赖:

  1. task A << {println 'Hello from A'}
  2. task B << {println 'Hello from B'}
  3. task C << {println 'Hello from C'}
  4.  
  5. B.dependsOn A
  6. C.dependsOn B

加入我们的新的task

  1. task B1 << {println 'Hello from B1'}
  2. B1.dependsOn B
  3. C.dependsOn B1

输出:

  1. paveldudka$ gradle C
  2. :A
  3. Hello from A
  4. :B
  5. Hello from B
  6. :B1
  7. Hello from B1
  8. :C
  9. Hello from C

注意dependsOn把task添加到依赖的集合中,所以依赖多个task是没有问题的。

  1. task B1 << {println 'Hello from B1'}
  2. B1.dependsOn B
  3. B1.dependsOn Q

输出:

  1. paveldudka$ gradle B1
  2. :A
  3. Hello from A
  4. :B
  5. Hello from B
  6. :Q
  7. Hello from Q
  8. :B1
  9. Hello from B1

mustRunAfter

现在假定我又一个task,它依赖于其他两个task。这里我使用一个真实的场景,我有两个task,一个单元测试的task,一个是UI测试的task。另外还有一个task是跑所有的测试的,它依赖于前面的两个task。

  1. task unit << {println 'Hello from unit tests'}
  2. task ui << {println 'Hello from UI tests'}
  3. task tests << {println 'Hello from all tests!'}
  4.  
  5. tests.dependsOn unit
  6. tests.dependsOn ui

输出:

  1. paveldudka$ gradle tests
  2. :ui
  3. Hello from UI tests
  4. :unit
  5. Hello from unit tests
  6. :tests
  7. Hello from all tests!

尽管unitest和UI test会子啊test task之前执行,但是unit和ui这两个task的执行顺序是不能保证的。虽然现在来看是按照字母表的顺序执行,但这是依赖于Gradle的实现的,你的代码中绝对不能依赖这种顺序。
由于UI测试时间远比unit test时间长,因此我希望unit test先执行。一个解决办法就是让ui task依赖于unit task。

  1. task unit << {println 'Hello from unit tests'}
  2. task ui << {println 'Hello from UI tests'}
  3. task tests << {println 'Hello from all tests!'}
  4.  
  5. tests.dependsOn unit
  6. tests.dependsOn ui
  7. ui.dependsOn unit // <-- I added this dependency

输出:

  1. paveldudka$ gradle tests
  2. :unit
  3. Hello from unit tests
  4. :ui
  5. Hello from UI tests
  6. :tests
  7. Hello from all tests!

现在unit test会在ui test之前执行了。
但是这里有个很恶心的问题,我的ui测试其实并不依赖于unit test。我希望能够单独的执行ui test,但是这里每次我执行ui test,都会先执行unit test。
这里就要用到mustRunAfter了。
mustRunAfter并不会添加依赖,它只是告诉Gradle执行的优先级如果两个task同时存在。比如我们这里就可以指定
ui.mustRunAfter unit,这样如果ui task和unit task同时存在,Gradle会先执行unit
test,而如果只执行gradle ui,并不会去执行unit task。

  1. task unit << {println 'Hello from unit tests'}
  2. task ui << {println 'Hello from UI tests'}
  3. task tests << {println 'Hello from all tests!'}
  4.  
  5. tests.dependsOn unit
  6. tests.dependsOn ui
  7. ui.mustRunAfter unit

输出:

  1. paveldudka$ gradle tests
  2. :unit
  3. Hello from unit tests
  4. :ui
  5. Hello from UI tests
  6. :tests
  7. Hello from all tests!

依赖关系如下图:

  1. mustRunAfterGradle2.4中目前还是实验性的功能。

finalizedBy

现在我们已经有两个task,unit和ui,假定这两个task都会输出测试报告,现在我想把这两个测试报告合并成一个:

  1. task unit << {println 'Hello from unit tests'}
  2. task ui << {println 'Hello from UI tests'}
  3. task tests << {println 'Hello from all tests!'}
  4. task mergeReports << {println 'Merging test reports'}
  5.  
  6. tests.dependsOn unit
  7. tests.dependsOn ui
  8. ui.mustRunAfter unit
  9. mergeReports.dependsOn tests

现在如果我想获得ui和unit的测试报告,执行task mergeReports就可以了。

  1. paveldudka$ gradle mergeReports
  2. :unit
  3. Hello from unit tests
  4. :ui
  5. Hello from UI tests
  6. :tests
  7. Hello from all tests!
  8. :mergeReports
  9. Merging test reports

这个task是能工作,但是看起来好笨啊。mergeReports从用户的角度来看感觉不是特别好。我希望执行tests task就可以获得测试报告,而不必知道mergeReports的存在。当然我可以把merge的逻辑挪到tests task中,但我不想把tests task搞的太臃肿,我还是继续把merge的逻辑放在mergeReports task中。
finalizeBy来救场了。顾名思义,finalizeBy就是在task执行完之后要执行的task。修改我们的脚本如下:

  1. task unit << {println 'Hello from unit tests'}
  2. task ui << {println 'Hello from UI tests'}
  3. task tests << {println 'Hello from all tests!'}
  4. task mergeReports << {println 'Merging test reports'}
  5.  
  6. tests.dependsOn unit
  7. tests.dependsOn ui
  8. ui.mustRunAfter unit
  9. mergeReports.dependsOn tests
  10.  
  11. tests.finalizedBy mergeReports

现在执行tests task就可以拿到测试报告了:

  1. paveldudka$ gradle tests
  2. :unit
  3. Hello from unit tests
  4. :ui
  5. Hello from UI tests
  6. :tests
  7. Hello from all tests!
  8. :mergeReports
  9. Merging test reports
  1. 注意,finalizedBy也是Gradle2.4的实验性功能

[Android Pro] Gradle tip #3-Task顺序的更多相关文章

  1. [Android Pro] Gradle Tips#1-tasks

    reference to : http://trickyandroid.com/gradle-tip-1-tasks/ http://blog.csdn.net/lzyzsd/article/deta ...

  2. [Android Pro] Gradle Tips#2-语法

    referece to : http://blog.csdn.net/lzyzsd/article/details/46935063 在第一篇博客中,我讲解了关于tasks和构建过程中task的不同阶 ...

  3. Gradle之Android Gradle Plugin 主要 Task 分析(三)

    [Android 修炼手册]Gradle 篇 -- Android Gradle Plugin 主要 Task 分析 预备知识 理解 gradle 的基本开发 了解 gradle task 和 plu ...

  4. 深入理解Android之Gradle

    深入理解Android之Gradle 格式更加精美的PDF版请到:http://vdisk.weibo.com/s/z68f8l0xTYrZt 下载 Gradle是当前非常"劲爆" ...

  5. Android studio gradle配置!!!【转】

    转自:http://www.open-open.com/lib/view/open1415793464648.html Gradle 基本概念 首先我们学习几个gradle 的脚本语法,掌握了这几个语 ...

  6. Android studio gradle配置完整版(转)

    Android studio gradle配置完整版https://my.oschina.net/u/1471093/blog/539075 Android studio 自定义打包apk名 - pe ...

  7. Android使用Gradle命令动态传参完成打包,不需要修改代码

    不得不说,Gradle很强大,有人会问Gradle是什么?这里也不细讲,在我认为他就是一个构建神器.Gradle 提供了: 一个像 Ant 一样的非常灵活的通用构建工具 一种可切换的, 像 Maven ...

  8. Android Studio] Gradle项目中添加JNI生成文件(.so文件)

    转:http://blog.csdn.net/qiujuer/article/details/24209457 为了适应潮流使用Android Studio还是有半年多了! 对于从Eclipse迁移项 ...

  9. Android studio gradle 打包 那些事

    总结了一下 目前觉得比较好用的gradle 和一些打包 经验.放在这里. 首先说下 渠道号 这个概念,我们经常会统计我们的api 访问来源 是来自于那个app store,这有利于 我们针对性的推广. ...

随机推荐

  1. Unix时间戳转换怎样在Excel批量修改?

    最近在操作项目的时候碰到一个Unix时间戳转换的问题."date_time":1393031347这个是什么,你知道吗?如果你对Unix时间戳了解的话一眼就看出来.但我们本着科普的 ...

  2. hihoCoder挑战赛11.题目4 : 高等理论计算机科学(LCA)

    clj在某场hihoCoder比赛中的一道题,表示clj的数学题实在6,这道图论貌似还算可以... 题目链接:http://hihocoder.com/problemset/problem/1167 ...

  3. ajax之get、post

    异步获取数据: <script type="text/javascript"> /** * [showstatus 获取数据] * @return {[type]} [ ...

  4. C#网络爬虫 WebUtility使用 转义字符 urlCode

    背景: 在C#写网络爬虫时候,有时候需要将html中的转义字符进行处理,还有网址中的中文处理 一.html转义字符处理 1.ASP.NET中的html解析 HttpUtility.HtmlDecode ...

  5. Android开源项目(二)

    第二部分 工具库 主要包括那些不错的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多媒体相关及其他. 一.依赖注入DI 通过 ...

  6. win7平台下React-Native Android:Unable to upload some APKs

    一.问题描述 根据网络上的Win7平台下React-native配置教程配置好开发环境的过程中,在艰难进行到react-native run-android这一步时,发现一直出现错误,截图如下: 错误 ...

  7. Android6.0以后动态增加权限

    private void test() throws IOException { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { in ...

  8. Unity 手指上下左右滑动的判定

    using UnityEngine; using System.Collections; public class jarodInputController : MonoBehaviour { pri ...

  9. OpenCV摄像头人脸识别

    注: 从外设摄像装置中获取图像帧,把每帧的图片与人脸特征进行匹配,用方框框住识别出来的人脸 需要用到的函数: CvHaarClassifierCascade* cvLoadHaarClassifier ...

  10. 小白死去活来的安装ros_qtc_plugin

    在距离写上一篇有关ROS的文章已经过去了很久了.在这段时间内一直在积累,盼望着能够厚积薄发,但还是被无情的社会折磨的死去活来,深深的体会到了一般学校和重点学校找工作的差别,以及用人单位的区别对待.说到 ...