总共分为三个阶段
1)初始化阶段
读取setting.gradle, 分析出项目包含的project及其他配置
2)配置阶段
递归配置根项目和下面的子项目,主要涉及配置分析即task构建,最后生成task依赖有向图
3)执行task
具体如下:
$ find . -name "*\.gradle"
./app/build.gradle
./build.gradle
./.gradle
./settings.gradle
$ cat settings.gradle
include ':app'
setting.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 {
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
***************************************************/
如需实时查看更多更新文章,请关注公众号"一点码客",一起探索技术