专栏名称: 鸿洋
你好,欢迎关注鸿洋的公众号,每天为您推送高质量文章,让你每天都能涨知识。点击历史消息,查看所有已推送的文章,喜欢可以置顶本公众号。此外,本公众号支持投稿,如果你有原创的文章,希望通过本公众号发布,欢迎投稿。
目录
相关文章推荐
鸿洋  ·  突发,这可能是软考最好过的一年! ·  3 天前  
郭霖  ·  一文了解 Gradle 插件 ·  5 天前  
鸿洋  ·  ANR?谁控制了触发时间? ·  5 天前  
鸿洋  ·  WebView 经历的各种干货方案分享 ·  6 天前  
郭霖  ·  使用 Jetpack Compose ... ·  1 周前  
51好读  ›  专栏  ›  鸿洋

Android Gradle Plugin插件详解

鸿洋  · 公众号  · android  · 2024-10-25 08:35

正文

前言

前面几篇文章我们讲解了关于关于Gradle的基础,Gradle生命周期,Gradle相关Api的讲解,以及Gradle自定义插件,Gradle Maven仓库管理。
今天这篇文章我们来讲解下Android Gradle Plugin相关知识。
简化起见:本文所指AGP:Android Gradle Plugin


1
`Gradle Plugin`和`AGP`的区别?


Gradle Plugin是Gradle构建过程中使用的插件的总称,而Android Gradle Plugin是这个总称里面的一个插件元素。
agp插件和gp插件区别

Android Gradle Plugin配合Gradle构建我们的应用apk。


2
apk构建流程


典型 Android 应用模块的构建流程。



按照以下常规步骤执行:
1.将源文件和class文件编译组合后编译为dex文件。
2.将资源文件转换为编译后的资源文件。
3.将dex文件和编译后的资源文件打包为apk文件。
4.使用签名工具对文件进行签名。
5.生成最终apk之前,会使用 zipalign 工具对应用进行优化,减小apk运行时内存。
在Gradle控制面板:执行assemble任务看看:
Line 172: > Task :application:preBuild UP-TO-DATE //编译预处理任务:空实现
    Line 176: > Task :application:preF1F3DebugBuild UP-TO-DATE //preF1F3DebugBuild F1F3变体预处理任务
    Line 180: > Task :application:compileF1F3DebugAidl NO-SOURCE //编译aidl文件
    Line 184: > Task :application:compileF1F3DebugRenderscript NO-SOURCE //编译绘制脚本文件
    Line 188: > Task :application:dataBindingMergeDependencyArtifactsF1F3Debug UP-TO-DATE //dataBinding依赖的类库或者插件合并
    Line 192: > Task :application:dataBindingMergeGenClassesF1F3Debug UP-TO-DATE //dataBinding依赖的class文件合并
    Line 196: > Task :application:generateF1F3DebugResValues UP-TO-DATE //生成ResValues 
    Line 200: > Task :application:generateF1F3DebugResources UP-TO-DATE//生成编译后的Resources
    Line 204: > Task :application:mergeF1F3DebugResources UP-TO-DATE //合并资源文件
    Line 208: > Task :application:dataBindingGenBaseClassesF1F3Debug UP-TO-DATE
    Line 212: > Task :application:dataBindingTriggerF1F3Debug UP-TO-DATE
    Line 216: > Task :application:generateF1F3DebugBuildConfig UP-TO-DATE 生成BuildConfig文件
    Line 220: > Task :application:javaPreCompileF1F3Debug UP-TO-DATE //java预编译
    Line 224: > Task :application:checkF1F3DebugAarMetadata UP-TO-DATE  //检测aar的元数据
    Line 228: > Task :application:createF1F3DebugCompatibleScreenManifests UP-TO-DATE 
    Line 232: > Task :application:extractDeepLinksF1F3Debug UP-TO-DATE
    Line 236: > Task :application:processF1F3DebugMainManifest UP-TO-DATE //处理MainManifest
    Line 240: > Task :application:processF1F3DebugManifest UP-TO-DATE //处理Manifest
    Line 244: > Task :application:processF1F3DebugManifestForPackage UP-TO-DATE//处理ManifestForPackage 
    Line 248: > Task :application:processF1F3DebugResources UP-TO-DATE//处理Resources
    Line 252: > Task :application:compileF1F3DebugJavaWithJavac UP-TO-DATE //编译原代码为class文件
    Line 256: > Task :application:compileF1F3DebugSources UP-TO-DATE//编译Sources
    Line 260: > Task :application:mergeF1F3DebugNativeDebugMetadata NO-SOURCE
    Line 264: > Task :application:mergeF1F3DebugShaders UP-TO-DATE
    Line 268: > Task :application:compileF1F3DebugShaders NO-SOURCE
    Line 272: > Task :application:generateF1F3DebugAssets UP-TO-DATE //生成Assets
    Line 276: > Task :application:mergeF1F3DebugAssets UP-TO-DATE //合并Assets
    Line 280: > Task :application:compressF1F3DebugAssets UP-TO-DATE //压缩Assets
    Line 284: > Task :application:checkF1F3DebugDuplicateClasses UP-TO-DATE //检测DuplicateClasses
    Line 288: > Task :application:desugarF1F3DebugFileDependencies UP-TO-DATE
    Line 292: > Task :application:mergeExtDexF1F3Debug UP-TO-DATE //合并des
    Line 296: > Task :application:processF1F3DebugJavaRes NO-SOURCE //处理JavaRes
    Line 300: > Task :application:mergeF1F3DebugJavaResource UP-TO-DATE //合并JavaResource
    Line 304: > Task :application:mergeLibDexF1F3Debug UP-TO-DATE //合并lib的dex
    Line 308: > Task :application:dexBuilderF1F3Debug UP-TO-DATE //dexBuilder
    Line 312: > Task :application:mergeProjectDexF1F3Debug UP-TO-DATE//mergeProjectDex
    Line 316: > Task :application:mergeF1F3DebugJniLibFolders UP-TO-DATE//合并JniLibFolders
    Line 320: > Task :application:mergeF1F3DebugNativeLibs UP-TO-DATE//合并NativeLibs
    Line 324: > Task :application:stripF1F3DebugDebugSymbols NO-SOURCE
    Line 328: > Task :application:validateSigningF1F3Debug UP-TO-DATE //检测签名
    Line 332: > Task :application:packageF1F3Debug UP-TO-DATE //打包变种
    Line 336: > Task :application:assembleF1F3Debug UP-TO-DATE//打包变种


可以看到打包apk的任务基本和前面图片里面描述的流程一致,整个过程都是编译然后合并,打包的过程。
主要涉及:
1.资源文件。
2.源文件。
3.库文件的资源。
4.库文件的class文件。
5.jni的静动态库信息。
6.manfest清单文件的创建。

7.签名校验等 其他生成一些配置文件。


3
`AGP`常用设置类型


1.buildTypes:编译类型:是debug或者release或者其他自定义类型。
android {
    defaultConfig {
        manifestPlaceholders = [hostName:"www.example.com"]
        ...
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {
            applicationIdSuffix ".debug"
            debuggable true
        }

        /**
         * The `initWith` property allows you to copy configurations from other build types,
         * then configure only the settings you want to change. This one copies the debug build
         * type, and then changes the manifest placeholder and application ID.
         */
        staging {
            initWith debug
            manifestPlaceholders = [hostName:"internal.example.com"]
            applicationIdSuffix ".debugStaging"
        }
    }
}


2.productFlavor:产品变种
创建产品变种与创建 build 类型类似:将其添加到 build 配置中的 productFlavors 代码块并添加所需的设置。产品变种支持与 defaultConfig 相同的属性,这是因为,defaultConfig 实际上属于 ProductFlavor 类。
这意味着,您可以在 defaultConfig 代码块中提供所有变种的基本配置,每个变种均可更改其中任何默认值,如 applicationId
// Specifies one flavor dimension.
flavorDimensions 'abi','version'
productFlavors {
    f1 {
        dimension 'abi'
        versionName '1.0'
    }
    f2 {
        dimension 'abi'
        versionName '2.0'
    }
    f3 {
        dimension 'version'
    }
    f4 {
        dimension 'version'
    }
}


对应的变体:
变体类型
3.build 变体
build 变体是 build 类型与产品变种的交叉产物,也是 Gradle 用来构建应用的配置
如上面的类型,编译时可选变体类型。
4.清单 (Manifest) 条目
在配置清单中可以设置Manifest清单中给的配置信息,如:
applicationId "com.example.myapp"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"


这些信息可以单独配置在不同给的变种中:如上面的类型,编译时可选变体类型:
这样可以针对不同变体设置不同的清单Manifest信息:
productFlavors {
    f1 {
        dimension 'abi'
        applicationId "com.example.myapp"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
    f2 {
        dimension 'x86'
        applicationId "com.example.myapp1"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 2
        versionName "2.0"
    }
}


配置清单中信息会覆盖原Manifest文件中的信息,当有多个清单配置时会合并。合并工具会根据每个清单文件的优先级按顺序合并,将所有清单文件组合到一个文件中。
例如,如果您有三个清单文件,则会先将优先级最低的清单合并到优先级第二高的清单中,然后再将合并后的清单合并到优先级最高的清单中,如图:


5.sourceSets:原文件文件目录
sourceSets {
    main {
        java {
            srcDirs = ['src/main/java']
        }
        res {
            srcDirs = ['src/main/res']
        }
        aidl {
            srcDirs = ['src/main/aidl']
        }
    }
}


6.signingConfigs:签名
Android 系统要求所有 APK 必须先使用证书进行数字签名,然后才能安装到设备上或进行更新。
signingConfigs {
    release {
        storeFile file("myreleasekey.keystore")
        storePassword "password"
        keyAlias "MyReleaseKey"
        keyPassword "password"
    }
}


7.compileOptions:指定当前编译的java版本信息
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}


8.buildFeatures:编译特色属性
buildFeatures {
    aidl = true
    buildConfig = true
    viewBinding = false
    dataBinding = true
}
//这个方式已经被弃用,后面源码可以看到弃用的地方
dataBinding {
    enabled = true
}


以上就是我们使用AGP时常用的插件配置项。

下面我们从源码去看下AGP插件内部原理。


4
`AGP插件`内部原理


1.源码查看方法

由于AGP插件源码大概有30多个g。所以不建议直接下载源码去阅读,可以直接在模块中引入就可以:
1.创建一个lib模块:
2.修改build.gradle中的代码:
apply plugin: 'java'
sourceCompatibility = 1.8
dependencies {
    implementation gradleApi()
    implementation 'com.android.tools.build:gradle:4.1.1'
}


同步代码后:可以在‘External Libraries’中查看源码。

2.查看源码

前面在讲解Gradle自定义插件的时候,说过,我们使用的每个插件都会在resources中进行声明。
全局搜索:
appplugin属性声明
找到
implementation-class=com.android.build.gradle.AppPlugin


进入AppPlugin看看:
/**
 * The plugin applied with `com.android.application'
 */

@Suppress("DEPRECATION")
class AppPluginBasePlugin() {
    override fun apply(project: Project) {
        super.apply(project)

        project.apply(INTERNAL_PLUGIN_ID)
    }
}

private val INTERNAL_PLUGIN_ID = mapOf("plugin" to "com.android.internal.application")


看到这里使用的INTERNAL_PLUGIN_ID中的plugin:com.android.internal.application
我们再次全局搜索下:com.android.internal.application
找到
implementation-class=com.android.build.gradle.internal.plugins.AppPlugin


进入
com.android.build.gradle.internal.plugins.AppPlugin


gradle源码:
gradle源码
查找apply方法:
在父类AbstractAppPlugin的父类BasePlugin找到了apply方法:
public final void apply(@NonNull Project project) {
    CrashReporting.runAction(
            () -> {
                //方法1
                basePluginApply(project);
                //方法2
                pluginSpecificApply(project);
            });
}


这里我们看方法1:
private void basePluginApply(@NonNull Project project) {
    // We run by default in headless mode, so the JVM doesn't steal focus.
    System.setProperty("java.awt.headless""true");

    this.project = project;
    //创建Project运行需要的服务信息
    createProjectServices(project);
    //获取Project的属性Options 
    ProjectOptions projectOptions = projectServices.getProjectOptions();
    //依赖检测
    DependencyResolutionChecks.registerDependencyCheck(project, projectOptions);
    //AndroidBasePlugin内部是一个空实现,需要我们自己去扩展。
    project.getPluginManager().apply(AndroidBasePlugin.class);
    //检测文件路径
    checkPathForErrors();
    //检测模块路径
    checkModulesForErrors();

    AttributionListenerInitializer.INSTANCE.init(
            project, projectOptions.get(StringOption.IDE_ATTRIBUTION_FILE_LOCATION));
    //agp的版本检测
    AgpVersionChecker.enforceTheSamePluginVersions(project);

    RecordingBuildListener buildListener = ProfilerInitializer.init(project, projectOptions);
    //注册buildListener构建的监听逻辑
    ProfileAgent.INSTANCE.register(project.getName(), buildListener);
    threadRecorder = ThreadRecorder.get();

    ProcessProfileWriter.getProject(project.getPath())
            .setAndroidPluginVersion(Version.ANDROID_GRADLE_PLUGIN_VERSION)
            .setAndroidPlugin(getAnalyticsPluginType())
            .setPluginGeneration(GradleBuildProject.PluginGeneration.FIRST)
            .setOptions(AnalyticsUtil.toProto(projectOptions));

    /**
    Gradle构建生命周期中的Agp插件的配置流程:
    1.configureProject:构建project配置、
    2.configureExtension:配置外部Extension字段
    3.createTasks:创建Tasks
    */

    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);
}


方法1主要任务:
• 做一些前期的检查工作,设置一些生命周期回调监听,创建任务等操作。
• Gradle构建生命周期中的Agp插件的配置流程:
1.configureProject:构建project配置、
2.configureExtension:配置外部Extension字段
3.createTasks:创建Tasks

看第一阶段:configureProject

private void configureProject() {
        final Gradle gradle = project.getGradle();

        //创建缓存版本变化的原因的字符串
        Provider cachedStringBuildServiceProvider =
                new ConstraintHandler.CachedStringBuildService.RegistrationAction(project)
                        .execute();
        ///** Build service used to cache maven coordinates for libraries. */
        Provider mavenCoordinatesCacheBuildService =
                new MavenCoordinatesCacheBuildService.RegistrationAction(
                                project, cachedStringBuildServiceProvider)
                        .execute();

        new LibraryDependencyCacheBuildService.RegistrationAction(project).execute();

        extraModelInfo = new ExtraModelInfo(mavenCoordinatesCacheBuildService);

        ProjectOptions projectOptions = projectServices.getProjectOptions();
        IssueReporter issueReporter = projectServices.getIssueReporter();

        //创建Aapt2工作的构建Service
        new Aapt2WorkersBuildService.RegistrationAction(project, projectOptions).execute();
        //创建一个Aapt2 Daemon的构建Service
        new Aapt2DaemonBuildService.RegistrationAction(project).execute();
        new SyncIssueReporterImpl.GlobalSyncIssueService.RegistrationAction(
                        project, SyncOptions.getModelQueryMode(projectOptions))
                .execute();
        Provider sdkComponentsBuildService =
                new SdkComponentsBuildService.RegistrationAction(
                                project,
                                projectOptions,
                                project.getProviders()
                                        .provider(() -> extension.getCompileSdkVersion()),
                                project.getProviders()
                                        .provider(() -> extension.getBuildToolsRevision()),
                                project.getProviders().provider(() -> extension.getNdkVersion()),
                                project.getProviders().provider(() -> extension.getNdkPath()))
                        .execute();

        projectOptions
                .getAllOptions()
                .forEach(projectServices.getDeprecationReporter()::reportOptionIssuesIfAny);
        IncompatibleProjectOptionsReporter.check(
                projectOptions, projectServices.getIssueReporter());

        // Enforce minimum versions of certain plugins
        GradlePluginUtils.enforceMinimumVersionsOfPlugins(project, issueReporter);

        // Apply the Java plugin
        project.getPlugins().apply(JavaBasePlugin.class);

        dslServices =
                new DslServicesImpl(
                        projectServices,
                        new DslVariableFactory(syncIssueReporter),
                        sdkComponentsBuildService);

        MessageReceiverImpl messageReceiver =
                new MessageReceiverImpl(
                        SyncOptions.getErrorFormatMode(projectOptions),
                        projectServices.getLogger());
        //将前面创建的所有服务放到globalScope对象中
        globalScope =
                new GlobalScope(
                        project,
                        creator,
                        dslServices,
                        sdkComponentsBuildService,
                        registry,
                        messageReceiver,
                        componentFactory);

        project.getTasks()
                .named("assemble")
                .configure(
                        task ->
                                task.setDescription(
                                        "Assembles all variants of all applications and secondary packages."));

        // As soon as project is evaluated we can clear the shared state for deprecation reporting.
        gradle.projectsEvaluated(action -> DeprecationReporterImpl.Companion.clean());

        createLintClasspathConfiguration(project);
    }


这个方法主要是创建了一系列构建需要的服务,并将服务放到一个globalScope对象中,也算是一些前期准备工作。

来看阶段2:`configureExtension`

private void configureExtension() {
        //获取dsl服务
        DslServices dslServices = globalScope.getDslServices();

        //获取构建输出
        final NamedDomainObjectContainer buildOutputs =
                project.container(BaseVariantOutput.class);

        project.getExtensions().add("buildOutputs", buildOutputs);

        //创建变体的工厂类
        variantFactory = createVariantFactory(projectServices, globalScope);
        //将前面创建的几个对象都放入到variantInputModel对象中:
        variantInputModel =
                new LegacyVariantInputManager(
                        dslServices,
                        variantFactory.getVariantType(),
                        new SourceSetManager(
                                project,
                                isPackagePublished(),
                                dslServices,
                                new DelayedActionsExecutor()));
        //这里创建了外部扩展Extension,进入到这个方法看看
        extension =
                createExtension(
                        dslServices, globalScope, variantInputModel, buildOutputs, extraModelInfo);

        globalScope.setExtension(extension);

        variantManager =
                new VariantManager<>(
                        globalScope,
                        project,
                        projectServices.getProjectOptions(),
                        extension,
                        variantFactory,
                        variantInputModel,
                        projectServices,
                        threadRecorder);

        registerModels(
                registry,
                globalScope,
                variantInputModel,
                extension,
                extraModelInfo);

        // create default Objects, signingConfig first as its used by the BuildTypes.
        variantFactory.createDefaultComponents(variantInputModel);

        createAndroidTestUtilConfiguration();
    }


进入createExtension方法:
这个是抽象方法:具体实现是在子类AppPlugin中:
protected AppExtension createExtension(
        @NonNull DslServices dslServices,
        @NonNull GlobalScope globalScope,
        @NonNull
                DslContainerProvider
                        dslContainers,
        @NonNull NamedDomainObjectContainer buildOutputs,
        @NonNull ExtraModelInfo extraModelInfo) {
    return project.getExtensions()
            .create(
                    "android",
                    getExtensionClass(),
                    dslServices,
                    globalScope,
                    buildOutputs,
                    dslContainers.getSourceSetManager(),
                    extraModelInfo,
                    new ApplicationExtensionImpl(dslServices, 
                    ));
}


可以看到这里创建了一个‘android’的Extensions,bean类型为:BaseAppModuleExtension
这个BaseAppModuleExtension类就是我们可以在外部做扩展的起始点,这个类中有哪些属性包括父类中的属性都可以被扩展:
进到这个类中看看:
/** The `android` extension for base feature module (application plugin).  */
open class BaseAppModuleExtension(...private val publicExtensionImplApplicationExtensionImpl)
:AppExtension:InternalApplicationExtension by publicExtensionImpl,。。


看到该类继承了AppExtensionInternalApplicationExtension(被ApplicationExtensionImpl代理)。
AppExtension又继承AbstractAppExtension继承TestedExtension继承BaseExtension
下面画出对应的类图关系:
Extentions扩展

这几个类组成了AGP所有的对外扩展属性。
这里列举几个平时项目中开发用到的字段:
1.在ApplicationExtensionImpl中:
buildFeatures属性:
public open val buildFeatures:com.android.build.api.dsl.ApplicationBuildFeatures


查看ApplicationBuildFeatures中的代码:
内部就两条属性:
//用于dataBinding支持
var dataBinding: Boolean?
var mlModelBinding: Boolean?


ApplicationBuildFeatures 继承 BuildFeatures,进入BuildFeatures 看看:
buidlFeatures.jt
可以看到这里面可以配置很多信息:
buildFeatures {
    aidl = true
    buildConfig = true
    viewBinding = false
    dataBinding = true
    ....
}


2.在AbstractAppExtension
val applicationVariants: DomainObjectSet =
        dslServices.domainObjectSet(ApplicationVariant::class.java)


这条属性,可以让我们在外部获取到当前所有变种:DomainObjectSet是一个集合,可以使用集合遍历方式:
android.applicationVariants.all {variant->
    variant.outputs.all {output->
        outputFileName ="landi_dev_v${variant.versionName}_${variant.name}"+".apk"
    }
}


相信这个代码大家在自己项目中或多或少都见过,通过前面分析我们就知道:
variant = ApplicationVariant类对象
output = BaseVariantOutput类对象


关于configureExtension就介绍到这。

第3阶段:`createTasks`

private void createTasks() {
        threadRecorder.record(
                ExecutionType.TASK_MANAGER_CREATE_TASKS,
                project.getPath(),
                null,
                () ->
                        TaskManager.createTasksBeforeEvaluate(
                                globalScope,
                                variantFactory.getVariantType(),
                                extension.getSourceSets()));

        project.afterEvaluate(
                CrashReporting.afterEvaluate(
                        p -> {
                            variantInputModel.getSourceSetManager().runBuildableArtifactsActions();

                            threadRecorder.record(
                                    ExecutionType.BASE_PLUGIN_CREATE_ANDROID_TASKS,
                                    project.getPath(),
                                    null,
                                    this::createAndroidTasks);
                        }));
    }


1.BeforeEvaluate:配置前创建一些task。
2.afterEvaluate:配置后创建一些task:进入createAndroidTasks看看:
 final void createAndroidTasks() {
        //使用variantManager创建变体 关注点1.。。
        variantManager.createVariants();
        //创建TaskManager 关注点2.。。
        TaskManager taskManager =
                createTaskManager(
                        variants,
                        variantManager.getTestComponents(),
                        !variantInputModel.getProductFlavors().isEmpty(),
                        globalScope,
                        extension,
                        threadRecorder);
        //使用TaskManager创建任务:关注点3.。。
        taskManager.createTasks();
        //这里设置Transforms的任务,如果外部有
        new DependencyConfigurator(project, project.getName(), globalScope, variantInputModel)
            .configureDependencySubstitutions()
            .configureGeneralTransforms()
            .configureVariantTransforms(variants, variantManager.getTestComponents());
        for (ComponentInfo variant : variants) {
            apiObjectFactory.create(variant.getProperties());
        }
        // lock the Properties of the variant API after the old API because
        // of the versionCode/versionName properties that are shared between the old and new APIs.
        variantManager.lockVariantProperties();

        // Make sure no SourceSets were added through the DSL without being properly configured
        variantInputModel.getSourceSetManager().checkForUnconfiguredSourceSets();

        // configure compose related tasks.
        taskManager.createPostApiTasks();

        ...
        GradleProperty.Companion.endOfEvaluation();

     }
     看关注点1:variantManager.createVariants();
     /** Creates the variants. */
    public void createVariants() {
        variantFactory.validateModel(variantInputModel);
        variantFactory.preVariantWork(project);

        computeVariants();
    }
    进入computeVariants:
     /** Create all variants. */
    private void computeVariants() {
        //获取所有flavorDimension放到List中
        List flavorDimensionList = extension.getFlavorDimensionList();

        //获取所有buildTypes和productFlavor信息:
        DimensionCombinator computer =
                new DimensionCombinator(
                        variantInputModel,
                        projectServices.getIssueReporter(),
                        flavorDimensionList);
        //计算所有的变体
        List variants = computer.computeVariants();
        //锁定变体
        variantApiServices.lockValues();
    }


关注点1主要作用就是获取所有的产品变体和buildTypes,创建对应的变体列表。
关注点2:createTaskManager
抽象方法在子类AppPlugin中实现:
protected ApplicationTaskManager createTaskManager(
            @NonNull
                    List>
                            variants,
            @NonNull
                    List<
                                    ComponentInfo<
                                            TestComponentImpl<
                                                    ? extends TestComponentPropertiesImpl>,
                                            TestComponentPropertiesImpl>>
                            testComponents,
            boolean hasFlavors,
            @NonNull GlobalScope globalScope,
            @NonNull BaseExtension extension,
            @NonNull Recorder threadRecorder) {
            return new ApplicationTaskManager(
                variants, testComponents, hasFlavors, globalScope, extension, threadRecorder);
        }
        }


创建的是一个ApplicationTaskManager类对象,后面会用到。
来看关注点3:
这里面其实就是创建一系列的task,篇幅太长,不一一介绍。
阶段三:createTasks主要任务:
1.根据Extensions中的信息创建所有变体。
2.给所有变体创建对应的任务:包括配置前任务和配置后的任务。
总结我们的AGP主要任务:
1.创建了一系列构建需要的服务,并将服务放到一个globalScope对象中,作为前期准备工作。
2.解析我们的外部扩展android{}闭包中的信息,设置到Project中。
3.根据buidTypes和产品变种创建对应的变种信息,创建一系列的构建任务。
好了,本文就讲解到这里了。
参考

Android构建官方文档

https://developer.android.google.cn/studio/build

补齐Android技能树——从AGP构建过程到APK打包过程

https://juejin.cn/post/6963527524609425415




最后推荐一下我做的网站,玩Android: wanandroid.com ,包含详尽的知识体系、好用的工具,还有本公众号文章合集,欢迎体验和收藏!


推荐阅读

简洁高效:类抖音视频列表设计思路
【Android】谷歌为什么不帮我默认实现啊,ImageGetter 和 TagHandler 的作用与区别
好用的HarmonyOS Next 横向、纵向下拉刷新控件



扫一扫 关注我的公众号

如果你想要跟大家分享你的文章,欢迎投稿~


┏(^0^)┛明天见!