美文网首页
Gradle理论与实践三:Gradle构建脚本基础

Gradle理论与实践三:Gradle构建脚本基础

作者: 饱醉豚我去年买了个表 | 来源:发表于2018-12-28 14:25 被阅读39次

    Gradle系列相关文章
    1、Gradle理论与实践一:Gradle入门
    2、Gradle理论与实践二:Groovy介绍
    3、Gradle理论与实践三:Gradle构建脚本基础
    4、Gradle理论与实践四:自定义Gradle插件
    5、Gradle配置subprojects和allprojects的区别:subprojects和allprojects的区别

    Gradle构建脚本基础

    • Project:根据业务抽取出来的一个个独立的模块

    • Task:一个操作,一个原子性操作。比如上传一个jar到maven中心库等

    • Setting.gradle文件:初始化及整个工程的配置入口

    • build.gradle文件:

    每个Project都会有个build.gradle的文件,是Project构建的入口。Root Project也有一个build.gradle文件,可以获取到所有的Child Project,并且可以对所有的Child Project进行统一配置:如应用的三方插件、三方依赖库等。如,我们可以在Root Project的build.gradle文件里配置:

    allprojects {
          repositories {
           jcenter()
          }
    }
    

    这样项目中所有依赖的三方库都可以在jcenter中下载了,省去了对每个Project去配置的情况。

    上面用到的是allprojects,还可以配置subprojects,他们的区别在于:allprojects是对所有project的配置,包括Root Project。而subprojects是对所有Child Project的配置。更详细的请移步:https://blog.csdn.net/u013700502/article/details/85231687

    1、创建一个task

    Task的创建方式,可以是:

    task hello {
         doFirst {
           print 'hello:doFirst\n'
         }
         doLast {
           print 'hello:doLast\n'
         }
    }
    

    也可以是:

    tasks.create("hello") {
         doFirst {
           print 'hello:doFirst'
         }
         doLast {
           print 'hello:doLast'
         }
    }
    

    他们执行的结果都是一样的:

    bogon:test_gradle mq$ gradle -q hello
    hello:doFirst
    hello:doLast
    

    task是Project对象的一个函数,原型为Task create(String name, Closure configureClosure),最后一个参数是闭包的时候,可以放到括号外面,并且括号可以省略,task中的doFirst和doLast分别在任务前后执行。

    2、创建Task的几种方式

    • 1、调用Project对象的task(String name)方法,如:
    def Task hello = task(hello);
    
    hello << {
        print 'hello\n'
    }
    

    输出:

    bogon:test_gradle mq$ gradle -q hello
    hello
    
    • 2、任务名字+闭包方式,如:
    task hello {
        description '任务描述'
        doLast {
            print "方法原型: Task task(String name, Closure configureClosure)\n"
            print "任务描述: ${description}"
        }
    }
    

    输出结果:

    bogon:test_gradle mq$ gradle -q hello
    方法原型: Task task(String name, Closure configureClosure)
    任务描述: 任务描述
    
    • 3、TaskContainer方式创建:
    tasks.create('hello') {
        description '任务描述'
        doLast {
            print "方法原型: Task create(String name, Closure configureClosure)\n"
            print "任务描述: ${description}"
        }
    }
    

    输出结果:

    方法原型: Task create(String name, Closure configureClosure)
    任务描述: 任务描述
    

    tasks是Project的属性,其类型是TaskContainer。其中1和2的创建最终也是调用TaskContainer方式创建的。

    3、Task内部执行顺序

    当我们执行Task的时候,就是执行其拥有的actions列表,是一个List。把Task执行之前、Task本身执行、Task之后执行分别称为doFirst、doSelf、doLast,先来看个例子:

    def Task hello = task myTask(type: CustomTask);
    
    hello.doFirst {
        print 'Task执行之前 do-First\n'
    }
    
    hello.doLast {
        print 'Task执行之后 do-Last\n'
    }
    
    class CustomTask extends DefaultTask {
    
        @TaskAction
        def doself() {
            print 'Task执行自身 do-self\n'
        }
    }
    

    输出:

    bogon:test_gradle mq$ gradle -q hello
    Task执行之前 do-First
    Task执行自身 do-self
    Task执行之后 do-Last
    

    通过结果发现确实是按照我们想要的顺序执行的。Gradle在执行hello这个任务的时候,Gradle会解析其带有@TaskAction注解的方法作为其Task执行的Action,并且把其加入到actionList中。而doFirst、doLast分别会在actionList的最前面和最后面加入,所以之后就达到了按顺序执行。

    4、Task任务依赖

    任务之间是可以有依赖关系的,使用dependsOn执行当前task依赖的任务,如:

    task hello << {
       print 'hello '
    }
    
    task world(dependsOn: hello) {
       doLast {
           print 'world'
       }
      }
    

    此时执行gradle -q world,结果如下:

    bogon:test_gradle mq$ gradle -q world
    hello world
    

    因为world任务是依赖hello的,所以当执行world后,先去执行了hello任务,再执行world任务。dependsOn是Task类的一个方法,可以接受多个依赖的任务作为参数。
    修改以下程序:

    task hello << {
       print 'hello\n'
    }
    
    task world(dependsOn: hello) {
       doLast {
           print 'world\n'
       }
    }
    
    world.doFirst {
       print 'doFirst\n'
    }
    
    world.doLast {
       print 'doLast2\n'
    }
    

    结果:

    bogon:test_gradle mq$ gradle -q world
    hello
    doFirst
    world
    doLast2
    

    通过结果可以看出,doFirst和doLast可以使用多次,并且按顺序执行。doLast可以用 << 操作符替代。

    5、自定义属性

    Project和Task允许添加额外自定义属性,通过对应的ext属性即可,如

    //自定义一个Project的属性
    ext.buildTime = '2018'
    
    //自定义多个属性
    ext {
       buildTime = '2018'
       month = '12'
    }
    
    task time {
         doLast {
           print "构建时间${buildTime} 年${month}月 \n"
         }
    }
    

    执行gradle -q time,执行结果:

    bogon:test_gradle mq$ gradle -q time
    构建时间2018 年12月
    

    可见我们自定义的属性正确地取到了,自定义属性的作用域很广,只要能得到对应的Project,就能获取到定义的属性值。在Android中我们通常使用自定义属性值来定义我们的版本号、版本名称等,把这些放到一个单独的gradle文件中,因为他们在发版前就会变动,放到单独的gradle文件中便于管理,在AS根目录下新建config.gradle如下:

    //config.gradle
    ext {
          android = [
                compileSdkVersion: 26,
                buildToolsVersion: "25.0.0",
                versionName      : "6.2.1",
                versionCode      : 6210,
                minSdkVersion    : 16,
                targetSdkVersion : 23
          ]
        }
    

    在APP对应的build.gradle中取值:

    //build.gradle
    apply from: rootProject.getRootDir().getAbsolutePath() + '/config.gradle'
    
    compileSdkVersion rootProject.ext.android.compileSdkVersion
    buildToolsVersion rootProject.ext.android.buildToolsVersion
    

    就可以获取到自定义的属性值。

    上例中,除了能获取到config.gradle中的属性值,还可以在builg.gradle中调用config.gradle中的方法,具体实现:

    //config.gradle
    ext {
        .......其他.........
        //注意方法和属性写法的区别
        copyApk = this.&copyApk
    }
    
    def copyApk() {
    
    }
    

    在build.gradle调用:

    //build.gradle
    apply from: rootProject.getRootDir().getAbsolutePath() + '/config.gradle'
    
    copyApk()
    

    这样就实现了在build.gradle中调用config.gradle中的copyApk()方法了。

    相关文章

      网友评论

          本文标题:Gradle理论与实践三:Gradle构建脚本基础

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