Android Gradle原理及机制深入分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/itchosen/article/details/86572570

Gradle构建流程

    总共分为三个阶段

        1)初始化阶段

            读取setting.gradle, 分析出项目包含的project及其他配置

        2)配置阶段

            递归配置根项目和下面的子项目,主要涉及配置分析即task构建,最后生成task依赖有向图

        3)执行task

    具体如下:

    

 Android gradle实例分析

目录结构

$ find . -name "*\.gradle"
./app/build.gradle
./build.gradle
./.gradle
./settings.gradle

setting.gradle

$ cat settings.gradle 
include ':app'

    setting.gradle配置了该项目包含哪些子项目

build.gradle分析

    build.gradle文件才是核心,在分析这个之前先了解下闭包代理

gradle闭包代理

根项目build.gradle

1,2,3中的biuldscript,dependencies其实是一个函数,相应的{}是一个闭包,并通过有相应代理类来执行这些闭包

buildscript(Closure) 是 Project 实例中调用的,传递的闭包的由ScriptHandler 执行

repositories(Closure) 是在 ScriptHandler实例中调用,传递的闭包由 RepositoryHandler 执行

dependencies(Closure) 是在 ScriptHandler 实例中调用,传递的闭包由 DependencyHandler 执行。

也就是说 jcenter() 是由 RepositoryHandler 调用

classpath(String) 是由 DependencyHandler(*) 调用

    但是,实际上如果查看DependencyHandler,也就是执行这个闭包的委托,它是没有classpath等方法的。其实这里涉及到Groory语音的另一个特性:methodMissing,它允许在运行时catch对于未定义方法的调用。实际上Gradle使用了MethodMixIn中声明的methodMissing,类似的机制在为定义的属性中也是一样的。相关的dependency操作可以在这里找到,它的行为如下:

    如果未定义方法的调用方有至少一个参数,如果存在configuration()与被调用方法有相同的名字,那么就根据参数的类型和数量,调用具有相关参数的doAdd方法。每个plugin都可以增进configuration到dependencies handler中,如Android插件增加了compile, compileClasspath, testCompile和一些其它配置here,Android 插件还增加了annotationProcessor配置,根据不同build类型和产品形式还有Compile, TestCompile等等。

    由于doAdd是私有方法,我们可以用对应的add公用方法重写上边的代码,当然不推荐啊:

    dependencies {    

        add('classpath','com.android.tools.build:gradle:3.2.0') 

        add('compile','io.reactivex.rxjava2:rxjava:2.1.2'') 

    }

  app的build.gradle

    application plugin将android方法被加入到了Project实例中,且将闭包传递的代理delegate赋值给了AppExtension,AppExtension定义了buildToolsVersion和compileSdkVersion方法,Android plugin使用这种方法接收所有的配置,包括default configuration,flavors等等。

groovy中的函数,如果有一个以上参数,可以省略(),所以其实上面的compileSdkVersion 28可以写成compileSdkVersion(28)

   那android函数又是在哪里添加到project里的呢?这个就在android.application这个插件里赋值的,比如通过extensions.create

   

//Plugin.java

class TestPluginExtension { 
    String message = 'Hello World'
    Closure callFunc = null;
}

class TestPlugin implements Plugin<Project> {
    void apply(Project project) {
        // Add the 'testExtension' extension object
        def extension = project.extensions.create('testExtension', TestPluginExtension)
        project.task('pluginTest') {
            doLast {
                println extension.message
                def closure = project['testExtension'].callFunc;
                closure('test');
            }
        }
    }
}

//build.gradle

testExtension { 
    message 'Hello Gradle'
    callFunc { name ->
        println 'hello,' + name
        return name
    }
}

还是看源码吧,只要编译过android程序,android plugin的源码也已经下载了的,

~/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle-core/2.1.0/12d90ede4c6ff93959a30d181acfb2187539b24c/gradle-core-2.1.0-sources.jar

~/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/2.1.0/bcae59215a7b71367ece66de0bfaff6441102aea/gradle-2.1.0-sources.jar

所以有AppExtension->TestedExtension->BaseExtension

BaseExtension就有android extension的各种函数,比如compileSdkVersion, buildTypes

/**************************************************
* 本文来自CSDN博主"老猿精选",喜欢请点关注
* 转载请标明出处:http://blog.csdn.net/itchosen
***************************************************/

猜你喜欢

转载自blog.csdn.net/itchosen/article/details/86572570