美文网首页Android技术知识Android开发经验谈Android开发
Gradle终于懂了(一)带你玩转Project

Gradle终于懂了(一)带你玩转Project

作者: 键盘上的麒麟臂 | 来源:发表于2019-07-20 10:40 被阅读27次

    本打算用gradle尝试着去写一些脚本方便项目的构建和打包,但是在复习gradle的时候有了一些新的理解,对gradle的理解不敢说精通,但也更透彻了,可以说是现在终于会写gradle了,所以打算从新写一个系列的文章来做个总结。
    之前也发布过一些关于gradle的文章
    浅谈Gradle(一)
    浅谈Gradle(二)与SourceSet
    Gradle排除依赖模块的某个类
    Gradle自定义插件实现自定义Task
    不要急,我不是让你去看这些东西,我是觉得当我回头去看以前写的这些东西,真的就是弟弟,那都是看大量别人的文章之后总结写出的,那也是别人的东西,怎么说呢,学了之后还是一种似懂非懂的感觉。这次不一样,这次我是看这个来写的,绝对权威绝对官方 https://docs.gradle.org/current/dsl/index.html,因为他本来就是官方。

    一. 浏览Gradle官方文档

    机翻之后的页面

    看到有很多内容,因为不止有android用到gradle嘛,左边还有个目录,入门那些的我们就不管了,进阶的也不管了,毕竟看到这里的多多少少也是写过一些gradle代码的,这章我们主要看这两个


    二. gradle构建的生命周期

    先简单讲讲生命周期吧,一些简单的东西我就不讲很详细了,比如一个项目有settings.gradle、根目录的build.gradle和模块build.gradle这些,就不详细讲了。
    看官网给出的介绍

    机翻看得变扭,就不翻译了
    看不懂没关系,至少我们能肯定的是构建过程有3个生命周期,Initialization、Configuration和Execution,我建议记住这3个单词,而不要总用中文的初始化、构建、执行去理解。官网下了还良心的给出了个Demo,告诉我们每个生命周期执行的阶段

    我不会kotlin所以就只讲groovy,其实差不多的。
    Initialization阶段会执行settings里面的代码,Configuration阶段会执行所有build.gradle里面的操作,无论是不是task,Execution阶段会执行action里面的操作(不懂什么是task什么是action的也别急,这里先了解下,往后学就知道了)所以这个Demo下面的内容我们不看,学其它的东西再回来看就豁然开朗了。

    三. Project

    我们直接讲Project,我记得我刚学gradle的时候经常看到有人写文章说gradle最重要的是Project、task和action,其实这样说确实能让新人很容易上手,却同样也很容易误导别人。
    但是从Project入手是不会有错的,真的了解Project是什么之后,你就真正的能看出gradle的架构,到时候task、action什么的就一目了然了。
    在上面截图的地方点击进入DSL参考



    进来后左边目录有什么 Build script blocks、Core types、 Publishing types、 Container types 之类的,内容很多,但是我们都不管,我们就看project,点击project




    进来之后看到Project下面有些概念,英文不好的朋友可以翻译看看这些概念,但是还是要记住他们的单词。
    1. project基本概念

    (1)Lifecycle 生命周期
    (2)Tasks 任务
    (3)Dependencies 依赖
    (4)Multi-project Builds 多项目构建
    (5)Plugins 插件
    (6)Properties 属性
    (9)Methods 方法

    2. 生命周期

    生命周期是说,project在Initialization阶段被创建,我们经常在settings.gradle写比如

    include ':app'
    

    在Initialization阶段执行这行代码,创建app这个模块的project对象,那就是说一般来说,每个module对应一个project对象。准确来说是gradle根据settings.gradle去找对应module的build.gradle来创建project对象,也就是说project就是build.gradle。
    所以project对象对应的代码在哪写,project在哪里创建,这些应该都很清楚了。

    3. Methods 方法

    task放到之后再写,我更倾向于单独拿一章出来写,其它的也应该分出来讲,要从浅入深,所以先讲Methods,因为它简单。
    把project当成一个对象,那这个对象里面有方法就很容易理解吧,先看看一般AS生成的build.gradle是怎样的,也就是project一般是怎样的(我随便找个Demo里面的app模块的代码)

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 27
        buildToolsVersion "27.0.0"
        defaultConfig {
            applicationId "com.tencent.tmgp.yybtestsdk"
            minSdkVersion 14
            targetSdkVersion 27
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    }
    
    

    我们先不要看android {......}里面的内容,这是plugin(插件)的知识,过滤掉之后

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    }
    

    是的,整个project里面只剩一个dependencies 方法,这里多嘴说一下,为什么说是方法。这个是一个闭包的写法,不知道的话建议先看看groovy语法中的闭包,一个参数的情况下是能省略括号的。

    然后看看project中有什么方法,其实还挺多的

    只截了一部分
    截图截不完,具体的可以看官网的API https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html
    我们随便拿一个方法来说,比如说getName,获取project的名称
    就这样写
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    }
    
    println this.getName()
    

    this就是指这个project嘛,代码会在Configuration生命周期中执行,打印



    嗯,我这个Module的名称就叫app,看得不过瘾没关系,我们可以再演示调用多一点的方法

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    }
    
    println this.getName()
    println this.getPath()
    println this.getRootDir()
    println this.getVersion()
    

    打印结果



    而且也能在文档中找到默认生成的dependencies



    看到了吧,传的参数是一个闭包(至于闭包里面写什么内容,那就要参照官网文档了)
    再比如文档中还有个ant​(Closure configureClosure)方法,那你就能这样写
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    }
    
    ant{
      ...........
    }
    

    那是不是只能在build.gradle里面调用文档中的方法,当然不是,当然也可以自己定义方法

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    }
    
    println this.getName()
    println this.getPath()
    println this.getRootDir()
    println this.getVersion()
    
    // 定义一个打印的方法
    def myfuction(String msg){
        println msg
    }
    myfuction("6666666")
    

    看结果


    上面演示的是在自己内部调用自己的project方法,那在别的project对象中调用该project的方法呢?怎么有点绕,就是一号project调用二号project的方法,要怎么操作。
    (为了节省时间,我拿我一个项目来说,这种情况肯定是多模块的情况)

    我们先理一下思路,要在一个project调用另一个project的方法要怎么做?当然是先拿到这个project对象,然后再调用它的方法。这时候我们API找到对project的操作(多说一句,看API最好看Javadoc)





    比较分散,可能没截完全部,总之在这个API中肯定是能找到的,光看上面的这些方法就知道能拿到所有能获取到的Project,简单说几个
    (1)比如getAllprojects(),返回当前的project和子project的集合(子project的意思是比如Moudule的project就是根目录project的子project)
    (2)比如getParent()就是获取父project
    (3)比如project​(String path)就是根据path获取project,有的人会问我怎么懂path是什么,没关系,你可以在对应的project中调用getPath()打印,就知道这个project的path是什么了(一般都是:app)。
    还有很多方法能获取到相对应的project。
    假如我在名为test的project中调用:app的project
    println "测试 "+project(":app").getRootDir()
    

    获取:app的根目录的地址,这样就行了,看得出什么不。
    project(":app").getRootDir() 和 this,getRootDir() 得到的结果是一样的,因为他们都是同一个根目录下。

    4. Properties

    文档中也有个Properties文档



    截不完图,详细的可以看文档,比如属性中有个常用的属性name,可以直接在project中获取。

    println "属性name "+name
    

    如果我们直接设值的话呢

    name = "mytest"
    println this.getName()
    

    会提示这个属性是只读的属性。
    想看关于这些属性更详细的信息的话,可以在文档下面找到Property details


    只截取一部分图

    你会发现属性后面有个只读的提示,name属性也是,所以无法直接这样修改属性。

    还有有个额外属性操作,就是ext关键字。
    在A的project中定义

    ext.testStr = "test 66666666666666"
    

    在B的project中调用

    println project(":app").ext.testStr
    

    这里先简单了解下这些原有的属性就行,在讲到插件的时候会解释更多。

    project就大概先提到这些吧,其它内容在讲到task、dependencies和plugin也会提到一些相关的内容,学了project的生命周期和一些属性、方法之后,对project相信也会有一定的了解。

    相关文章

      网友评论

        本文标题:Gradle终于懂了(一)带你玩转Project

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