gradle_tranform.md

May 25, 2018 · View on GitHub

新增Gradle Transform

监听文件编译结束,通过javasist实现字节码修改,实现代码插入,通过这种插件化的AOP 和代码中使用Aspectj 区别就是,避免代码碎片化,添加一个功能修改多处代码,即使用了Aspectj 也许要在修改的地方添加注解,当修改处很多的时候很不方便,通过transform和javassist 可以遍历整个工程,按照满足条件的一次性修改,并且以后我们可以写成通用性的组建,比如自动注册一些组建在所有Activity,里面Javassist用了反射原理,但是这是编译器,不损失效率,Javassist非常强大,需要仔细学习

1.新建一个MyTransform 再新建一个插件MyPlugin注册这个Transform

Mytransform 重写transform方法 里面要将输入内容复制给输出,否者报错,这是第一步,其实就是相当于在运行我们给拦截了,必须再把内容输出出去才能打包成dex

里面遍历

// Transform的inputs有两种类型,一种是目录,一种是jar包,要分开遍历 inputs.each { TransformInput input -> //对类型为“文件夹”的input进行遍历 input.directoryInputs.each { DirectoryInput directoryInput -> //文件夹里面包含的是我们手写的类以及R.class、BuildConfig.class以及R$XXX.class等

            /**
             * 这里就统一处理一些逻辑,避免代码分散,碎片化
             */

            println("transform transformsalkfjdl;kajf#####################*********")
            println(directoryInput.file.absolutePath)
            MyInject.injectDir(directoryInput.file.absolutePath,"com\\wangpos\\test",project)

            // 获取output目录
            def dest = outputProvider.getContentLocation(directoryInput.name,
                    directoryInput.contentTypes, directoryInput.scopes,
                    Format.DIRECTORY)

            // 将input的目录复制到output指定目录
            FileUtils.copyDirectory(directoryInput.file, dest)
        }
        //对类型为jar文件的input进行遍历
        input.jarInputs.each { JarInput jarInput ->

            //jar文件一般是第三方依赖库jar文件

            // 重命名输出文件(同目录copyFile会冲突)
            def jarName = jarInput.name
            def md5Name = DigestUtils.md5Hex(jarInput.file.getAbsolutePath())
            if (jarName.endsWith(".jar")) {
                jarName = jarName.substring(0, jarName.length() - 4)
            }
            //生成输出路径
            def dest = outputProvider.getContentLocation(jarName + md5Name,
                    jarInput.contentTypes, jarInput.scopes, Format.JAR)
            //将输入内容复制到输出
            FileUtils.copyFile(jarInput.file, dest)
        }
   }