内容简介:之前为了优化内部的Route, 去看了下本篇源码基于android gradle 3.0.1的版本.<!--more-->
之前为了优化内部的Route, 去看了下 TransformAPI
, 然后就顺便看了下 AppPlugin
的源码
本篇源码基于android gradle 3.0.1的版本.
<!--more-->
总入口
我们直接从入口 apply
开始看, 他调到了父类 BasePlugin
的apply方法.
protected void apply( Project project) { // 一些基础path和插件版本的校验 // 以及一些流程记录的初始化 ... // 真正执行的是configureProject方法 // 项目配置 threadRecorder.record( ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE, project.getPath(), null, this::configureProject); threadRecorder.record( ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION, project.getPath(), null, this::configureExtension); threadRecorder.record( ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION, project.getPath(), null, this::createTasks); } public interface Recorder { ... // record方法用来执行block, 然后将执行结果记录 void record( ExecutionType executionType, String projectPath, String variant, VoidBlock block); }
apply
入口的代码非常简洁, 主要执行就三个方法, configureProject
, configureExtension
和 createTasks
, 看方法名可以猜到, 他们的作用应该是配置Project, 配置插件的Extensions, 并且创建任务(task).
configureProject
private void configureProject() { extraModelInfo = new ExtraModelInfo(projectOptions, project.getLogger()); checkGradleVersion(); sdkHandler = new SdkHandler(project, getLogger()); // sdk, dependence的下载 if (!project.getGradle().getStartParameter().isOffline() && projectOptions.get(BooleanOption.ENABLE_SDK_DOWNLOAD) && !projectOptions.get(BooleanOption.IDE_INVOKED_FROM_IDE)) { SdkLibData sdkLibData = SdkLibData.download(getDownloader(), getSettingsController()); sdkHandler.setSdkLibData(sdkLibData); } // 构建androidBuilder androidBuilder = new AndroidBuilder( project == project.getRootProject() ? project.getName() : project.getPath(), creator, new GradleProcessExecutor(project), new GradleJavaProcessExecutor(project), extraModelInfo, getLogger(), isVerbose()); dataBindingBuilder = new DataBindingBuilder(); dataBindingBuilder.setPrintMachineReadableOutput( extraModelInfo.getErrorFormatMode() == ExtraModelInfo.ErrorFormatMode.MACHINE_PARSABLE); // Apply the Java and Jacoco plugins. // JavaBasePlugin, 用于编译 java 代码成class, 并组装成一个jar文件 project.getPlugins().apply(JavaBasePlugin.class); project.getPlugins().apply(JacocoPlugin.class); // 设置assmble task的描述 project.getTasks() .getByName("assemble") .setDescription( "Assembles all variants of all applications and secondary packages."); // 注册编译监听 // 会在每个project build结束后调用到, 而不单是当前的project project.getGradle() .addBuildListener( new BuildListener() { public void buildStarted(Gradle gradle) { TaskInputHelper.enableBypass(); } public void settingsEvaluated(Settings settings) {} public void projectsLoaded(Gradle gradle) {} public void projectsEvaluated(Gradle gradle) {} public void buildFinished(BuildResult buildResult) { // 复合构建时不会多次重复清除 if (buildResult.getGradle().getParent() != null) { return; } // 清除dex缓存 ExecutorSingleton.shutdown(); sdkHandler.unload(); threadRecorder.record( ExecutionType.BASE_PLUGIN_BUILD_FINISHED, project.getPath(), null, () -> { PreDexCache.getCache() .clear( FileUtils.join( project.getRootProject() .getBuildDir(), FD_INTERMEDIATES, "dex-cache", "cache.xml"), getLogger()); Main.clearInternTables(); }); } }); // 注册taskGraph构建完成时的回调 project.getGradle() .getTaskGraph() .addTaskExecutionGraphListener( taskGraph -> { TaskInputHelper.disableBypass(); // 遍历所有task, 如果是dexTransform, 则读取对应的dexTransform的缓存 for (Task task : taskGraph.getAllTasks()) { if (task instanceof TransformTask) { Transform transform = ((TransformTask) task).getTransform(); if (transform instanceof DexTransform) { PreDexCache.getCache() .load( FileUtils.join( project.getRootProject() .getBuildDir(), FD_INTERMEDIATES, "dex-cache", "cache.xml")); break; } } } }); }
看代码我们可以梳理 configureProject
流程如下
- 校验gradle版本
- 下载dependence
-
构建
androidBuilder
-
如果有设置
dataBinding
, 则会构建dataBindingBuilder
(这个不在本篇重点) -
分别引用
JavaBasePlugin
和JacocoPlugin
插件, 分别用于编译java代码成class和用于检查测试用例的覆盖率 - 注册taskGraph构建准备时的回调, 在准备完成时读取DexTransform的dex-cache缓存
- 注册编译完成时的回调, 进行dex缓存的清除工作 ### configureExtension
private void configureExtension() { // 分别创建buildType, ProductFlavor, SigningConfig, BaseVariantOutput对应存储的集合对象, 设置默认的Extensions final NamedDomainObjectContainer<BuildType> buildTypeContainer = project.container( BuildType.class, new BuildTypeFactory(instantiator, project, extraModelInfo)); final NamedDomainObjectContainer<ProductFlavor> productFlavorContainer = project.container( ProductFlavor.class, new ProductFlavorFactory( instantiator, project, project.getLogger(), extraModelInfo)); final NamedDomainObjectContainer<SigningConfig> signingConfigContainer = project.container(SigningConfig.class, new SigningConfigFactory(instantiator)); final NamedDomainObjectContainer<BaseVariantOutput> buildOutputs = project.container(BaseVariantOutput.class); // 设置project的buildOutputs属性的扩展为buildOutputs project.getExtensions().add("buildOutputs", buildOutputs); // 在appPlugin中实现, 创建android扩展属性 extension = createExtension( project, projectOptions, instantiator, androidBuilder, sdkHandler, buildTypeContainer, productFlavorContainer, signingConfigContainer, buildOutputs, extraModelInfo); // ndk处理器实例化 ndkHandler = new NdkHandler( project.getRootDir(), null, /* compileSkdVersion, this will be set in afterEvaluate */ "gcc", "" /*toolchainVersion*/, false /* useUnifiedHeaders */); FileCache buildCache = BuildCacheUtils.createBuildCacheIfEnabled(project, projectOptions); GlobalScope globalScope = new GlobalScope( project, projectOptions, androidBuilder, extension, sdkHandler, ndkHandler, registry, buildCache); // ApplicationVariantFactory variantFactory = createVariantFactory(globalScope, instantiator, androidBuilder, extension); // ApplicationTaskManager, 管理application的任务创建 taskManager = createTaskManager( globalScope, project, projectOptions, androidBuilder, dataBindingBuilder, extension, sdkHandler, ndkHandler, registry, threadRecorder); // 变体的创建和管理的管理器 variantManager = new VariantManager( globalScope, project, projectOptions, androidBuilder, extension, variantFactory, taskManager, threadRecorder); // 注册自定义 工具 模型, 和native工具模型 registerModels(registry, globalScope, variantManager, extension, extraModelInfo); // map the whenObjectAdded callbacks on the containers. signingConfigContainer.whenObjectAdded(variantManager::addSigningConfig); buildTypeContainer.whenObjectAdded( buildType -> { SigningConfig signingConfig = signingConfigContainer.findByName(BuilderConstants.DEBUG); buildType.init(signingConfig); variantManager.addBuildType(buildType); }); productFlavorContainer.whenObjectAdded(variantManager::addProductFlavor); // map whenObjectRemoved on the containers to throw an exception. signingConfigContainer.whenObjectRemoved( new UnsupportedAction("Removing signingConfigs is not supported.")); buildTypeContainer.whenObjectRemoved( new UnsupportedAction("Removing build types is not supported.")); productFlavorContainer.whenObjectRemoved( new UnsupportedAction("Removing product flavors is not supported.")); // create default Objects, signingConfig first as its used by the BuildTypes. variantFactory.createDefaultComponents( buildTypeContainer, productFlavorContainer, signingConfigContainer); }
configureExtension
主要处理了 extension
- 分别创建buildType, ProductFlavor, SigningConfig, BaseVariantOutput对应存储的集合对象
-
创建android Extension,
createExtension
是个抽象方法, 具体实现代码可以看AppPlugin
里, 在我们的工程配置gradle文件里, 就是我们熟悉的android闭包里的配置
protected BaseExtension createExtension( Project project, ProjectOptions projectOptions, Instantiator instantiator, AndroidBuilder androidBuilder, SdkHandler sdkHandler, NamedDomainObjectContainer<BuildType> buildTypeContainer, NamedDomainObjectContainer<ProductFlavor> productFlavorContainer, NamedDomainObjectContainer<SigningConfig> signingConfigContainer, NamedDomainObjectContainer<BaseVariantOutput> buildOutputs, ExtraModelInfo extraModelInfo) { return project.getExtensions() .create( "android", AppExtension.class, project, projectOptions, instantiator, androidBuilder, sdkHandler, buildTypeContainer, productFlavorContainer, signingConfigContainer, buildOutputs, extraModelInfo); }
-
分别创建
taskManager
和variantManager
, 看名字就可以知道他负责的分别是task和variant - 针对签名配置signingConfig, buildType, productFlavor 注册新增时候的监听, 对应添加到variantManager中做管理. 同时, 他们是不支持删除的.
- 创建默认的variant
createTasks
private void createTasks() { threadRecorder.record( ExecutionType.TASK_MANAGER_CREATE_TASKS, project.getPath(), null, // 在before evaluate新增部分tasks () -> taskManager.createTasksBeforeEvaluate( new TaskContainerAdaptor(project.getTasks()))); project.afterEvaluate( project -> threadRecorder.record( ExecutionType.BASE_PLUGIN_CREATE_ANDROID_TASKS, project.getPath(), null, () -> createAndroidTasks(false))); }
在 createTask
阶段, 首先会在配置收集之前(即在apply plugin)阶段会创建一些task, 这里 TaskContainerAdaptor
可以理解为对task的又一层管理封装.
在配置收集获取所有task之后, 我们会调用到 createAndroidTasks
在执行真正的创建tasks之前, 主要是对extension内一些配置进行校验, 譬如针对buildToolsVersion, compileSdkVersion是否指定, 是否另外引用了JavaPlugin等等, 这里的代码可以自行看源码了解
final void createAndroidTasks(boolean force) { ... threadRecorder.record( ExecutionType.VARIANT_MANAGER_CREATE_ANDROID_TASKS, project.getPath(), null, // 根据variant创建tasks () -> { variantManager.createAndroidTasks(); ApiObjectFactory apiObjectFactory = new ApiObjectFactory( androidBuilder, extension, variantFactory, instantiator, project.getObjects()); for (VariantScope variantScope : variantManager.getVariantScopes()) { BaseVariantData variantData = variantScope.getVariantData(); apiObjectFactory.create(variantData); } }); ... }
这里我们可以主要看下 variantManager.createAndroidTasks()
方法内容, 这里根据variant创建对应的tasks
可以看到具体流程如下:
- 校验是否引用apt插件(这在3.0里使用annotationProcessor来声明注解处理器)
- 填充收集所以variant
- 根据variant创建对应的tasks
public void createAndroidTasks() { variantFactory.validateModel(this); // 校验是否引用apt插件, 如果有, 抛出异常 variantFactory.preVariantWork(project); final TaskFactory tasks = new TaskContainerAdaptor(project.getTasks()); if (variantScopes.isEmpty()) { recorder.record( ExecutionType.VARIANT_MANAGER_CREATE_VARIANTS, project.getPath(), null /*variantName*/, // 填充所有variant this::populateVariantDataList); } // Create top level test tasks. recorder.record( ExecutionType.VARIANT_MANAGER_CREATE_TESTS_TASKS, project.getPath(), null /*variantName*/, // 创建测试tasks () -> taskManager.createTopLevelTestTasks(tasks, !productFlavors.isEmpty())); for (final VariantScope variantScope : variantScopes) { recorder.record( ExecutionType.VARIANT_MANAGER_CREATE_TASKS_FOR_VARIANT, project.getPath(), variantScope.getFullVariantName(), // 根据variant创建不同的tasks, 创建assemble任务也在这里 () -> createTasksForVariantData(tasks, variantScope)); } taskManager.createReportTasks(tasks, variantScopes); }
总结
最后我们总结下, appPlugin
apply
的整体流程(当然, 因为他执行的是父类的 apply
, 所以流程适用于 libraryPlugin
)
-
project的配置
- 检验gradle版本
- 下载dependence
-
构建
androidBuilder
-
引用
JavaBasePlugin
和JacocoPlugin
- 定义编译过程的回调, 负责处理dex-cache的加载和清除工作
-
extension的配置
- 创建和配置extension
- 创建taskManager和variantManager
- 配置签名设置, buildType, productFlavor, 供后续task以及编译时使用
-
创建task(任务)
- 一些extension设置的检验
- 编译task的创建
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- ReactNative源码解析-初识源码
- Spring源码系列:BeanDefinition源码解析
- Spring源码分析:AOP源码解析(下篇)
- Spring源码分析:AOP源码解析(上篇)
- 注册中心 Eureka 源码解析 —— EndPoint 与 解析器
- 新一代Json解析库Moshi源码解析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据挖掘十大算法
(美)吴信东(Xindong Wu)、(美),库玛尔 ,(Vipin Kumar) / 李文波、吴素研 / 清华大学出版社 / 2013-5 / 39.00元
《世界著名计算机教材精选:数据挖掘十大算法》详细介绍了在实际中用途最广、影响最大的十种数据挖掘算法,这十种算法是数据挖掘领域的顶级专家进行投票筛选的,覆盖了分类、聚类、统计学习、关联分析和链接分析等重要的数据挖掘研究和发展主题。《世界著名计算机教材精选:数据挖掘十大算法》对每一种算法都进行了多个角度的深入剖析,包括算法历史、算法过程、算法特性、软件实现、前沿发展等,此外,在每章最后还给出了丰富的习......一起来看看 《数据挖掘十大算法》 这本书的介绍吧!