建设银行网站未响应,如何快速搭建网站,找室内设计师上哪个网站,建设农业网站的论文随着android的组件化的到来#xff0c;一个项目后期功能越来越多#xff0c;模块拆分的越来越多#xff0c;作为android的开发的小伙伴就不得不面对运行一下android项目可能需要5,6分钟甚至10几分钟的等待期#xff0c;开发时间都浪费在编译上了#xff0c;你说烦不烦呢一个项目后期功能越来越多模块拆分的越来越多作为android的开发的小伙伴就不得不面对运行一下android项目可能需要5,6分钟甚至10几分钟的等待期开发时间都浪费在编译上了你说烦不烦呢那么怎么解决这个困境总不能就这么一直凑合着吧反正也没太大影响开发只是速度慢了一点而已。
那么怎么让编译加快呢自从把eclipse改用android studio之后后出现了一种新的引用格式aaraar格式是编译好的资源和类那么有没有一种可能将主模块依赖的的所有模块库转化为aar依赖在某个模块库变化的时候将它转化为aar依赖不变化的时候转化为库依赖那么编译速度会不会大大提高答案是肯定的了。有人为说了把库都部署到maven不就行了当然maven远程库确实有这个功效但是每写一个新的模块库是不是都得把它部署到maven上有没有一种可能就是写一个脚本插件上这么新的模块自动转化为Maven的库文件这种方案就就非常ok了。
要实现这个方案首先咱们要面对以下这些问题
需要通过 gradle plugin 的形式动态修改没有改动过的 module 依赖为 相对应的 aar 依赖如果 module 改动退化成 project 工程依赖这样每次只有改动的 module 和 app 两个模块编译。需要把 implement/api moduleB修改为implement/api aarB并且需要知道插件中如何加入 aar 依赖和剔除原有依赖需要构建 local maven 存储未被修改的 module 对应的 aar也可以通过 flatDir 代替速度更快编译流程启动需要找到哪一个 module 做了修改需要遍历每一个 module 的依赖关系进行置换 module 依赖怎么获取一次性能获取到所有模块依赖还是分模块各自回调修改其中一个模块依赖关系会阻断后面模块依赖回调每一个 module 换变成 aar 之后自身依赖的 child 依赖 网络依赖aar,给到 parent module (如何找到所有 parent module) ? 还是直接给 app module ? 有没有 app 到 module 依赖断掉的风险 这里需要出一个技术方案。需要hook 编译流程完成后置换 loacal maven 中被修改的 aar
1、如何手动添加 aar 依赖分析implement 源码实现入口在 DynamicAddDependencyMethods 中的 tryInvokeMethod 方法。他是一个动态语言的 methodMissing 功能 public DynamicInvokeResult tryInvokeMethod(String name, Object... arguments) {//省略部分代码 ...return DynamicInvokeResult.found(this.dependencyAdder.add(configuration, normalizedArgs.get(0), (Closure)null));}private class DirectDependencyAdder implements DependencyAdderDependency {private DirectDependencyAdder() {}public Dependency add(Configuration configuration, Object dependencyNotation, Nullable Closure configureAction) {return DefaultDependencyHandler.this.doAdd(configuration, dependencyNotation, configureAction);}}public Dependency add(String configurationName, Object dependencyNotation) {return this.add(configurationName, dependencyNotation, (Closure)null);}public Dependency add(String configurationName, Object dependencyNotation, Closure configureClosure) {//这里直接调用到了 doAdd return this.doAdd(this.configurationContainer.getByName(configurationName), dependencyNotation, configureClosure);}
而 doAdd 方法三个参数通过 debug 源码发现configuration 就是 implementation, api, compileOnly 这三个字符串生成的对象dependencyNotation 是一个 LinkHashMap 有两个键值对分别是 name:aarName, ext:aar,最后一个configureAction 传 null 就可以了调用 project.dependencies.add 最终会调到 doAdd 方法也就是说直接调用 add 即可。
2、localMave 优先使用 flatDir 实现通过指定一个缓存目录 getLocalMavenCacheDir 把生成 aar/jar 包丢进去,依赖修改时候通过 上面的 4.1 添加对应的 aar 即可
fun flatDirs() {val map mutableMapOfString, File()map.put(dirs, File(getLocalMavenCacheDir()))appProject.rootProject.allprojects {it.repositories.flatDir(map)}}
3、编译流程启动需要找到哪一个 module做了修改
使用遍历整个项目的文件的 lastModifyTime 去做实现已每一个 module 为一个粒度递归遍历当前 module 的文件把每个文件的 lastModifyTime 整合计算得出一个唯一标识 countTime通过 countTime 与上一次的作对比,相同说明没改动,不同则改动. 并需要同步计算后的 countTime 到本地缓存中
计算每个module文件改变的时间代码如下 project.rootProject.allprojects.onEach {if (it project.rootProject || it.childProjects.isNotEmpty()) {returnonEach}var countTime 0Lit.projectDir.eachFileRecurse { file -// 过滤掉build目录及该目录下的所有文件isCodeFile !(file.isDirectory Contants.BUILD file.name)if (isCodeFile) {countTime file.lastModified()count}returneachFileRecurse isCodeFile}newModuleList.add(ModuleChangeTime(it.path, countTime))}
原理就是将所有moudle下的代码和资源的最后修改时间累加在编译的时候对比前后时间如果一只就用aar依赖如果不一致就用项目依赖。
4、module 依赖关系 project 替换成 aar 技术方案 每一个 module 依赖关系替换的遍历顺序是无序的所以技术方案需要支持无序的替换目前使用的方案是如果当前模块 A 未改动需要把 A 通过 localMaven 置换成 A.aar,并把 A.aar 以及 A 的 child 依赖给到第一层的 parent module 即可
5、hook 编译流程完成后置换 loacal maven 中被修改的 aar //如果当前模块是改动模块需要打 aarif (mAllChangedProject?.contains(childProject.path) true) {//打包aarval bundleTask getBundleTask(childProject, buildType.capitalize())?.apply {task.configure {it.finalizedBy(this)}}if (enableLocalMaven) {// publish local mavenbundleTask?.let { bTask -LogUtil.d(bTask$bTask)val buildType if (bTask.name.contains(release)) {Release} else {Debug}try {val publishMavenTask childProject.project.tasks.named(publishMaven${buildType}PublicationToLocalRepository).orNullpublishMavenTask?.let {bTask.finalizedBy(it)}} catch (e: Throwable) {e.printStackTrace()}}} else {//copy aarval localMavenTask childProject.tasks.maybeCreate(uploadLocalMaven buildType.capitalize(),FlatTask::class.java)localMavenTask.localMaven thisAarFlatLocalMavenbundleTask?.finalizedBy(localMavenTask)}}
这些代码的意思就是获取将每个moudle转化为aar的任务然后在这个任务结束后创建新的任务FlatTask将这些aar放到localMaven中。FlatTask源码如下 open class FlatTask : DefaultTask() {Internalvar inputPath: String? nullInternalvar inputFile: File? nullInternalvar outputPath: String? nullInternalvar outputDir: File? nullInternallateinit var localMaven: AarFlatLocalMavenTaskActionfun uploadLocalMaven() {val flatAarName getFlatAarName(project)this.inputPath FileUtil.findFirstLevelAarPath(project)this.outputPath FileUtil.getLocalMavenCacheDir()inputFile inputPath?.let { File(it) }outputDir File(this.outputPath)inputFile?.let {File(outputDir, flatAarName .aar).let { file -if (file.exists()) {file.delete()}}it.copyTo(File(outputDir, flatAarName .aar), true)localMaven.putIntoLocalMaven(flatAarName, flatAarName .aar)}}}}