Android Gradle文件拆解

Gradle是一种Groovy语言编写的构建工具。
在Android中的运用主要在于 build.gradlesettings.gradle
我们可以先从 Android的build.gradle(project)中去研究它的东西。

1.build.gradle(Project)

先随便找里面一段代码出来:
在这里插入图片描述
因为用groovy语言写的,所以不懂的其所以然的人会觉得这段代码的结构有点奇怪。
但是因为之前学过kotlin,上面这段代码的结构其实就是一个闭包,也叫做 一等函数支持。里面的参数 repositories、google()、jcenter()都是作为参数传入到 allprojects()这个函数中的。
:所谓闭包,就是可以把A函数作为参数传入到B函数中使用。在Java中是没有这种概念的,但是有与差不多的做法,就是监听器的回调方法。这里我就不多介绍了,之前的Kotlin中有讲到这种概念:Kotlin学习(5)函数与函数式编程
上述的代码其实就是相当于这样:

allprojects(new Action<Project>() {
    @Override
    void execute(Project project) {
        project.repositories{
            google()
            jcenter()
        }
    }
})

2.build.gradle(app)

2.1 buildTypes

表示的是该模块是给哪个人群用的。

  • debug表示是给自己用的。
  • relase表示是给外部人用的
  • internal表示是给内部人用的

在这里插入图片描述
如果你在项目目录下构建 debug、release或者internal的包,那么gradle会自动的关联main和对应的包的代码,这样,代码就会形成了不同的模式。
一般项目会默认有两种type,可以根据Android Studio最左边的Build Variant查看:
在这里插入图片描述
表示当前有两个版本,debug和release版本,通过切换版本,或者在对应的包上编写代码,我们可以给不同的群体用不同的App。并且在编译器在安装这些版本的时候,别的版本的代码是会忽略掉的,所以这样并不会导致APK体积增大或者效率变慢。

2.2 productFlavors

它的作用和buildTypes差不多,但是它又多了一层维度。这层维度是我们可以定义的一个维度。
比如,我们要在App原有的 debug(自己用)、relase(发布版)的上面,再加一层 付费版和免费版。
这样多一个维度后,就变成了: debug免费版、debug付费版、relase免费版、relase付费版,看下下面代码:

android {
    ...
    //注意在声明productFlavors前,要声明flavorDimensions
    flavorDimensions 'cost'
    //其中free和paid是自己定义的维度,这个方法并不是groovy定义,而是通过闭包的特性被创建出这么一个方法出来
    productFlavors {
        free {
        }
        paid {
        }
    }
}

构建好后,接下来再去查看Build Variants,就可以看到在原来的 debug、release又多了一个维度:
在这里插入图片描述
是不是觉得已经有点帮助了呢?
flavorDimensions声明了维度的属性,可以自己定义,上面的 free和paid属于付不付钱的属性,所以我给它起名叫cost(你也可以叫别的)。我完全还可以在这上面,再多一层维度:

  //在付费版、免费版属性的基础上,再多加一个国际化的属性
  flavorDimensions 'cost', 'nation'
    productFlavors {
        free {
            dimension 'cost'
        }
        paid {
            dimension 'cost'
        }
       
        china {
            dimension 'nation'
        }
        international{
            dimension 'nation'
        }
    }

其中china一个版、国际一个版,并用 dimension来声明它是声明属性的
在这里插入图片描述
这样子看,项目突然就复杂了起来,但是这样子确实是对一些需求很复杂、工程量很大的项目,划分的稍微清晰、维护也方便了一点。这就有点像后台服务端的正式服、测试服这么一个说法。这种做法针对当前产品做出来的,具体该怎么用,或者用还是不用,都是可以很快讨论出来的。

2.3 dependencies

在这里插入图片描述
从闭包的角度去理解的话,implementation ‘xxxxx’ 其实就是跟下面的代码差不多

//下面是伪代码:implementation 'xxxxx' 
denpendenciesHandler.add('implementation','xxxxx')

compile、implementation、api的区别
complie在2018年被弃用,使用implementation和api取代之。而为什么会有这么一个现象,在于他们有不同的作用。
注1:首先compile、implementation、api这三个依赖方法并不是针对、解决远程依赖的问题的(因为我们单项目里用的很多都是远程的开源框架),因为这些远程框架他们更新的频率很低。而用来解决本地依赖所产生的一些问题!!!!!!
下面举例的Aproject、Bproject、Cproject的三个都是本地的项目。
注2:打包和编译是两个分开的概念。

  • compile
    传递依赖。
    假如Aproject 通过compile依赖Bproject, 并且Bproject 通过compile依赖了 Cproject,就产生了一条依赖链A->B->C
    那么编译之后,Aproject能够用引用Cproject的内容。
    但这样做是由劣势的,因为如果Cproject 进行了改变,那必然会导致Bproject进行一次重新的编译,而Bproject重新的编译会导致Aproject也会进行一次重新编译。
    假设如果Cproject改变了很多,那么整个依赖链都会产生多次重新编译。
    再假设如果Cproject的改变,Aproject实际上用不到,那么对于A来说,就产生了浪费(因为编译后这些C的东西已经确确实实存在了)。
    这就是为什么complie被弃用的原因。
  • implementation
    不会传递依赖
    如果Aproject 通过implementation依赖了 Bproject,并且Bproject通过 implementation依赖了Cproject,这个时候的依赖链就是 A->B B->C
    改变C对A来说并不会重新编译。而是只对B来说会重新编译。这样就能减少资源、性能的浪费
  • api
    和implementation没有太大的区别

3. gradlew

作为一个命令,可以通过 ./gradlew 或者 gradlew执行它。它的作用是运行gralde配置文件
如果本地没有任何gradle文件,则执行这个命令会生成一个gradle文件。
在这里插入图片描述

4. gradle-wrapper.properties

在这里插入图片描述
该文件会声明gradle的工具的版本 -all表示能查看greadle的源码,-bin则为不能

5. settings.gradle

Android项目因为组件化的原因,可以包含多个子项目
如下图所示:整个项目由app、Aproject、Bproject组成
在这里插入图片描述
在grandle运行的时候,先会去找settings.gradle,查看里面的 include是否包含本项目。比如本project(app)在include里面,那么就会确定自己是多项目中的主项目。
也就是说,settings.gralde是在gralde运行时判断本组件为 多组件项目中的主组件还是 子组件(有点拗口)
它是初始化阶段时做的。

关于doLast doFirst

在task中可以使用doLast、doFirst在调用这个task时,调用里面的方法

doLast{
...
}

doFirst{
....
}

他们定义了任务执行顺序。 doFrist插进去的任务在第一个执行,doLast在doFirst后执行

发布了248 篇原创文章 · 获赞 99 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/rikkatheworld/article/details/103718090
今日推荐