[关闭]
@Awille 2018-12-15T09:29:09.000000Z 字数 3871 阅读 120

自定义插件 IconVersion的实现

Android Gradle Plugin


gradle的基本认识

Gradle是一个构建工具,它是用来帮助我们构建app的,构建包括编译、打包等过程。
在解析 Gradle 的编译过程之前我们需要理解在 Gradle 中非常重要的两个对象。Project和Task。

每个项目的编译至少有一个 Project,一个 build.gradle就代表一个project,每个project里面包含了多个task,task 里面又包含很多action,action是一个代码块,里面包含了需要被执行的代码。

整个project我们的gradle文件结构
MyProject
|-----module1
    |-----build.gradle //模块1 gradle
|-----module2
    |-----build.gradle //模块2 gradle
|-----build.gradle //整个项目的gradle,其配置会被应用到整个项目当中
|-----setting.gradle //定义哪些module会被加到编译过程

Gradle脚本的执行时序

Gradle脚本的执行分为三个过程:

初始化
分析有哪些module将要被构建,为每个module创建对应的 project实例。这个时候settings.gradle文件会被解析。

配置:处理所有的模块的 build 脚本,处理依赖,属性等。这个时候每个模块的build.gradle文件会被解析并配置,这个时候会构建整个task的链表(这里的链表仅仅指存在依赖关系的task的集合,不是数据结构的链表)。

执行:根据task链表来执行某一个特定的task,这个task所依赖的其他task都将会被提前执行。

IconVersion的实现原理

整个project的编译过程是由一个个task执行实现的。
整个app基本 编译打是由 application插件实现的

apply plugin: 'com.android.application'

AppPluin部分 源码解析:

首先查看其apply方法:

@Override
public void apply(@NonNull Project project) {
    super.apply(project);
}

此处调用了父类的apply方法:

@Override
public void apply(@NonNull Project project) {
    // We run by default in headless mode, so the JVM doesn't steal focus.
    //省略初始化与错误检查
    threadRecorder = ThreadRecorder.get();//初始化线程信息记录者
    ProcessProfileWriter.getProject(project.getPath())
            .setAndroidPluginVersion(Version.ANDROID_GRADLE_PLUGIN_VERSION)
            .setAndroidPlugin(getAnalyticsPluginType())
            .setPluginGeneration(GradleBuildProject.PluginGeneration.FIRST)
            .setOptions(AnalyticsUtil.toProto(projectOptions));
    BuildableArtifactImpl.Companion.disableResolution();
    if (!projectOptions.get(BooleanOption.ENABLE_NEW_DSL_AND_API)) {//检查是否是最新的api
        TaskInputHelper.enableBypass();
        threadRecorder.record(
                ExecutionType.BASE_PLUGIN_PROJECT_CONFIGURE,
                project.getPath(),
                null,
                this::configureProject);
                //在配置工程阶段,主要做的是创建一些后续阶段会用到的对象,其中最重要的当属androidBuilder
        threadRecorder.record(
                ExecutionType.BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION,
                project.getPath(),
                null,
                this::configureExtension);
        //配置扩展阶段,其实做的事和之前阶段一样,也是创建对象,在创建的这些对象中,
        //大家会看到个单词——variant,这就是常说的构建变体。
        threadRecorder.record(
                ExecutionType.BASE_PLUGIN_PROJECT_TASKS_CREATION,
                project.getPath(),
                null,
                this::createTasks);
    //plugin的task创建
    } else {
        //省略旧版实现
    }
}

查看调用了三次的record方法的实现:

回头看basePlugin里的3个回调方法configureProject、configureExtension、

createTasks,方法里传的type已经暴露了他们的作用:

1、BASE_PLUGIN_PROJECT_CONFIGURE:plugin的基础设置、初始化工作

2、BASE_PLUGIN_PROJECT_BASE_EXTENSION_CREATION:EXTENSION的初始化工作

3、BASE_PLUGIN_PROJECT_TASKS_CREATION:plugin的task创建

最终找到创建项目task的方法:

@Override
public void createTasksForVariantScope(@NonNull final VariantScope variantScope) {
    //............
    // Add a task to publish the applicationId.
    createApplicationIdWriterTask(variantScope);
    // Add a task to process the manifest(s)
    recorder.record(
            ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_MANIFEST_TASK,
            project.getPath(),
            variantScope.getFullVariantName(),
            () -> createMergeApkManifestsTask(variantScope));
    // Add a task to create the res values
    recorder.record(
            ExecutionType.APP_TASK_MANAGER_CREATE_GENERATE_RES_VALUES_TASK,
            project.getPath(),
            variantScope.getFullVariantName(),
            () -> createGenerateResValuesTask(variantScope));
    // Add a task to merge the resource folders
    recorder.record(
            ExecutionType.APP_TASK_MANAGER_CREATE_MERGE_RESOURCES_TASK,
            project.getPath(),
            variantScope.getFullVariantName(),
            (Recorder.VoidBlock) () -> createMergeResourcesTask(variantScope, true));
    recorder.record(
            ExecutionType.APP_TASK_MANAGER_CREATE_PROCESS_RES_TASK,
            project.getPath(),
            variantScope.getFullVariantName(),
            () -> {
                // Add a task to process the Android Resources and generate source files
                createApkProcessResTask(variantScope);
                // Add a task to process the java resources
                createProcessJavaResTask(variantScope);
            });
    //..............
}

assemble依赖的task大致包括:
1、applicationIdWriter:发布
2、ApplicationIdmergeApkManifests:处理清单文件
3、generateResValues:生成ResValues
4、compileJavaWithJavac:编译java文件
5、mergeAssets收集所有assetspackage:打包生成apk
6、processResource:处理资源文件

实现iconCover,其中processResource这个task就是我们的关注点,可以在这个task上加一些action来实现我们的功能。

该插件实现的具体细节:

BaseVariant 不同的版本变体
applicationVariant 整个应用的变体集合
GraphicsEnviroment
具体见技术分享的ppt(这个内容是我做的技术分享)
ppt地址:
自定义插件
密码: HA5T

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注