• Transform介绍(1)


    img

    使用Transform的常见场景有埋点统计、耗时监控、方法替换

    通过上图以我们了解下transform的作用,transform在 class 到 dex 之间工作,处理包括 javac 编译后的字节码文件,每个 transform 都对应一个 Task,transform 的输入和输出对应 transform task 的输入输出。每个 transform task 的输出都分别存储在app\build\intermediates\transform\[Transform Name]\[Variant]

    1. transform 方法

    Transfom 的几个核心API可以查看 buildSrc方式 - transform 下的介绍,这里我们着重挑 transform 方法做下介绍

     @Override
        void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
            super.transform(transformInvocation)
            println '转换开始........................'
    
            def start = System.currentTimeMillis()
            def inputs = transformInvocation.inputs
            def outputProvider = transformInvocation.outputProvider
    
            if (outputProvider != null)
                outputProvider.deleteAll()
    
            // transform 的 inputs 有两种类型:一种是目录,一种是jar包
            inputs.each { input ->
                // 本地 project 编译成的多个 class 文件存放的目录
                input.directoryInputs.each { dir ->
                    handleDirectory(dir,outputProvider)
                }
                // 各依赖锁编译成的 jar 文件
                input.jarInputs.each { jar ->
                    handleJar(jar, outputProvider)
                }
            }
            def cost = (System.currentTimeMillis() - start) / 1000
            println "转换结束............................:$cost"
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • getInputs:获取 TransformInput 对象,它是消费型输入内容,对应 getScopes() 定义的范围,transformInput 由两部分组成
      • DirectoryInput 集合:以源码方式参与构建的输入文件,包括完整的源码目录结构及其中的源码文件
      • JarInput集合:以jaraar依赖方式参与构建的输入文件,包含本地依赖和远程依赖
    • getOutPutProvider:获取 TransformOutputProvider 对象,它是对输出文件的描述,它有两个功能
      • deleteAll:当 transform 以非增量构建模式时,需要删除上一次构建产生的所有中间文件,可以使用该方法
      • getContentLocation:获得指定范围+类型的输出目标路径

    2. transform 增量模式

    任何构建系统都会尽量避免重复执行相同工作,transform 也提供了这样的备选项

    1. 增量标记位

      • Transform#isIncremental():返回 true 才会触发增量模式
      • TransformInvocation#isIncremental():表示 TransformTask 是否增量执行
    2. Task 增量模式与 Transform 增量模式区别

      前者会跳过整个 Task 的动作列表,后者还是会依次执行 TransformTask,但输入内容胡增加变更内容信息

    3. 增量模式的输入

      此模式下的输入都是带状态的,需要根据这些状态做不同处理,无需每次都执行所有流程;例如新增的输入需要处理,未修改的输入就无需处理,Transform 定义了4个输入文件状态

      // com.android.build.api.transform\Status.java
      @Deprecated
      public enum Status {
          // 未修改,无需处理,也无需复制操作
          NOTCHANGED,
          // 新增,正常处理并复制给下一个任务
          ADDED,
          // 已修改,正常处理并复制给下一个任务
          CHANGED,
          // 已删除,需同步移除 OutputProvider 指定的目标文件
          REMOVED;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

    3. 注册 Transform

    Gradle:com.android.tools.build:gradle-7.0.2.jar 下的 BaseExtension 中维护了 Transform 列表,自定义 Transform 需要注册才能生效,并且还支持设置 TransformTask 的依赖

    // com.android.build.gradle\BaseExtension.kt
    bstract class BaseExtension protected constructor(
        protected val dslServices: DslServices,
        protected val globalScope: GlobalScope,
        ...
        ):AndroidConfig, Lockable {
        private val _transforms: MutableList<Transform> = mutableListOf()
        /** Secondary dependencies for the custom transform. */
        private val _transformDependencies: MutableList<List<Any>> = mutableListOf()
        
        ...
        fun registerTransform(transform: Transform, vararg dependencies: Any) {
            _transforms.add(transform)
            _transformDependencies.add(listOf(dependencies))
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    注册 Transform:

    // 获取 Android 扩展
    val androidExt = project.extensions.getByType(BaseExtension::class.java)
    // 注册 Transform,支持额外增加依赖
    androidExt.registerTransform(MyTransform())
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    JavaWeb三大组件之Listener------Listener详细讲解
    【Visual Leak Detector】源码编译 VLD 库
    Python学习笔记(22)-Python框架22-PyQt框架使用(常用控件)
    智能金融决策策略,规则引擎在大数据金融行业的实战案例
    什么样的性能测试工具才算是好的工具呢?
    Sql注入产生原因及威胁
    C++学习——位操作
    Docker安装GitLab及使用图文教程
    pdf文档内容提取pdfplumber、PyPDF2
    HCIE-Security Day44:AC产品概述、功能、架构组成、AC准入主要技术、RADIUS协议
  • 原文地址:https://blog.csdn.net/qq_37776700/article/details/127645991