IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 编译优化探索3 -> 正文阅读

[移动开发]Android 编译优化探索3

前言

本小节讲解编译优化中关于R文件优化与kotlin 1.6.10的问题

我们首先抛出一个来自官方的问题
在这里插入图片描述
问题链接

我们发现修改布局中某个控件id,在kotlin 1.6.10中kaptgenerate任务与compile任务会触发全量编译

kotlin 1.6.10 引起KaptGenerate全量问题

要探索这个问题其实要前提了解部分增量源码机制

哪些task的输入可以被增量?
@Incremental与@SkipWhenEmpty标注的输入可以被增量
举例如下:

abstract class MyTask : DefaultTask() {

    //可以被感知增量
    @OutputDirectory
    @Incremental
    abstract fun getOutputDir(): DirectoryProperty?

    //可以被感知增量
    @OutputDirectory
    @SkipWhenEmpty
    abstract fun getOutputDir2(): DirectoryProperty?


    //无法感知
    @InputFiles
    abstract fun getSourceFiles(): ConfigurableFileCollection?

    @TaskAction
    fun action(inputChange: InputChanges) {
        //inputChange 可以感知 getOutputDir getOutputDir2的变化
        //但是如果getSourceFiles改变将触发全量编译
    }
}

Gradle运行时DefaultExecutionStateChangeDetector这个类中会进行增量判断

//DefaultExecutionStateChangeDetector.java
public class DefaultExecutionStateChangeDetector implements ExecutionStateChangeDetector {
	  @Override
    public ExecutionStateChanges detectChanges(AfterPreviousExecutionState lastExecution, BeforeExecutionState thisExecution, Describable executable, IncrementalInputProperties incrementalInputProperties) {
        // Capture changes in execution outcome
        ChangeContainer previousSuccessState = new PreviousSuccessChanges(
            lastExecution.isSuccessful());

        // Capture changes to implementation
        ChangeContainer implementationChanges = new ImplementationChanges(
            lastExecution.getImplementation(), lastExecution.getAdditionalImplementations(),
            thisExecution.getImplementation(), thisExecution.getAdditionalImplementations(),
            executable);

        // Capture non-file input changes
        ChangeContainer inputPropertyChanges = new PropertyChanges(
            lastExecution.getInputProperties(),
            thisExecution.getInputProperties(),
            "Input",
            executable);
        ChangeContainer inputPropertyValueChanges = new InputValueChanges(
            lastExecution.getInputProperties(),
            thisExecution.getInputProperties(),
            executable);

        // Capture input files state
        ChangeContainer inputFilePropertyChanges = new PropertyChanges(
            lastExecution.getInputFileProperties(),
            thisExecution.getInputFileProperties(),
            "Input file",
            executable);
        InputFileChanges nonIncrementalInputFileChanges = incrementalInputProperties.nonIncrementalChanges(
            lastExecution.getInputFileProperties(),
            thisExecution.getInputFileProperties()
        );

        // Capture output files state
        ChangeContainer outputFilePropertyChanges = new PropertyChanges(
            lastExecution.getOutputFileProperties(),
            thisExecution.getOutputFileProperties(),
            "Output",
            executable);
        OutputFileChanges outputFileChanges = new OutputFileChanges(
            lastExecution.getOutputFileProperties(),
            thisExecution.getOutputFileProperties()
        );

        // Collect changes that would trigger a rebuild
        ChangeContainer rebuildTriggeringChanges = errorHandling(executable, new SummarizingChangeContainer(
            previousSuccessState,
            implementationChanges,
            inputPropertyChanges,
            inputPropertyValueChanges,
            outputFilePropertyChanges,
            outputFileChanges,
            inputFilePropertyChanges,
            nonIncrementalInputFileChanges
        ));
        ImmutableList<String> rebuildReasons = collectChanges(rebuildTriggeringChanges);

        if (!rebuildReasons.isEmpty()) {
            return new NonIncrementalDetectedExecutionStateChanges(
                rebuildReasons,
                thisExecution.getInputFileProperties(),
                incrementalInputProperties
            );
        } else {
            // Collect incremental input changes
            InputFileChanges directIncrementalInputFileChanges = incrementalInputProperties.incrementalChanges(
                lastExecution.getInputFileProperties(),
                thisExecution.getInputFileProperties()
            );
            InputFileChanges incrementalInputFileChanges = errorHandling(executable, caching(directIncrementalInputFileChanges));
            ImmutableList<String> incrementalInputFileChangeMessages = collectChanges(incrementalInputFileChanges);
            return new IncrementalDetectedExecutionStateChanges(
                incrementalInputFileChangeMessages,
                thisExecution.getInputFileProperties(),
                incrementalInputFileChanges,
                incrementalInputProperties
            );
        }
    }
}

其中我们来拆解一下这个类中重要的代码段

        //收集会触发全量编译的原因
        ChangeContainer rebuildTriggeringChanges = errorHandling(executable, new SummarizingChangeContainer(
            previousSuccessState,//之前的运行状态是否成功等
            implementationChanges,//实现类
            inputPropertyChanges,//task输入的属性字段是否改变(这里指代的非文件类型的输入)
            inputPropertyValueChanges,//task输入的属性字段对应的数值是否改变(这里指代的非文件类型的输入)
            outputFilePropertyChanges,//task输出的属性字段是否改变(这里说的输出字段是文件类型)
            outputFileChanges,//task输出的文件是否改变(这里说的输出是文件类型)
            inputFilePropertyChanges,//task 输入文件类型字段是否改变(文件类型字段)
            nonIncrementalInputFileChanges//task 非增量类型的字段与数值是否改变
        ));
        
        //注意上面并没有收集增量类型文件对应的value的改变
        
        //如果上面的比较发现有不一样的状态会返回对应字符串从而触发全量编译
        ImmutableList<String> rebuildReasons = collectChanges(rebuildTriggeringChanges);
        if (!rebuildReasons.isEmpty()) {
            return new NonIncrementalDetectedExecutionStateChanges(
                rebuildReasons,
                thisExecution.getInputFileProperties(),
                incrementalInputProperties
            );
        } else {
            // 收集增量信息 这里就是我们常说的产生增量数据的地方
            InputFileChanges directIncrementalInputFileChanges = incrementalInputProperties.incrementalChanges(
                lastExecution.getInputFileProperties(),
                thisExecution.getInputFileProperties()
            );
            InputFileChanges incrementalInputFileChanges = errorHandling(executable, caching(directIncrementalInputFileChanges));
            ImmutableList<String> incrementalInputFileChangeMessages = collectChanges(incrementalInputFileChanges);
            return new IncrementalDetectedExecutionStateChanges(
                incrementalInputFileChangeMessages,
                thisExecution.getInputFileProperties(),
                incrementalInputFileChanges,
                incrementalInputProperties
            );

在kotlin 1.6.10会将R.jar文件改动放入nonIncrementalInputFileChanges中,且对应的字段为$1,如果搜索整个源码会发现找不到这个字段,具体原因是这个字段是匿名动态赋值到KaptGernerate任务中如下代码:

Task myTask =tasks.maybeCreate("hello")
myTask.inputs.file("xxx/R.jar")

解决方案字节码修改相关代码即可,但是我最后发现1.6.20修复了这个问题

R 文件引起的compile全量问题

在AGP 3.6版本后不在生成R.java而是直接生成R.jar这样会加速整个编译过程,但是Gradle当前无法感知内部jar文件变化(答案来自官方论坛)。
在最新版本的kotlin中也没有解决相关问题。

因此笔者自己用了奇淫技巧去规避整个问题。

AGP的GenerateLibraryRFileTask生产出R.jar文件与R.txt.您可以直接修改这个Task还原会AGP之前的版本即可,在赋值给Compile任务的输入即可
在这里插入图片描述
但是这个方案实现比较麻烦最后因为没有时间就放弃了。于是我们可以利用R.jarR.txt自己生产一个R.java即可,但是需要中间Task作为桥接:

在这里插入图片描述

修正后的基准测试对比图

在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-07 22:51:12  更:2022-04-07 22:52:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 21:01:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码