随着app的持续迭代更新,新功能的持续集成等缘由。项目中的library project愈来愈多。android
特别是最近一两年来。流行起来了组件化,这更是直接增长了不少的本地library project的数量。致使每次须要打包apk运行时,都会须要对全部module都进行再次编译。严重影响打包速度。git
Speedup是一款专用于对多module环境下进行打包加速的gradle插件。主要依赖的基本原理有两个:github
咱们先来看看常规多module环境下的打包流程:api
从上图能够看到。每次打包的时候。都会通过如下几个步骤:bash
而若是。咱们使用maven依赖的方式进行依赖的话。编译流程就会优化成下图所示的方式:网络
能够看到。与上面直接使用module依赖的方式相比:使用Maven仓库依赖的方式,因为maven仓库中提供的直接就是已打包好的aar依赖,因此直接干掉了module -> aar打包编译的过程,起到了加速编译的做用!并发
因此,如今咱们就能够得出第一个结论:使用maven依赖比使用module依赖更快速!app
因此这个时候。不少人的常规作法就是。想办法将这些module依赖的library,编译打包发布到各自的远程中央仓库中去,这样就能避免每次运行的时候都去进行额外编译,从而节省时间了。maven
可是这种作法存在几个问题:
因此将module打包发布到远程仓库的作法,并不可取!
如今咱们来考虑一下,若是将仓库设置在本地会怎样?也就是说使用本地maven仓库进行依赖管理。
咱们来列举一下这里使用本地依赖的优势:
本地仓库中version不惟一:
便可以作到同版本覆盖发布,修改代码后直接从新发布便可,不须要提高version版本。这也正是远程仓库所作不到的。可避免频繁升级改动。
本地仓库不与网络打交道。
读取依赖更快速。事实上,远程仓库中所依赖的库,也是先存放到本地仓库中去再进行读取的。
能够看到,使用本地仓库,能够完美的解决频繁发包的问题!由于若是你的library不须要频繁修改的话,你确定也早就已经把它单独拆出去放远程仓库中去了~
因此咱们只要解决依赖不统一的问题。那么这个加速方案就算是完全打通了!
打包任务这里特指的assembleXXX任务。这个任务相信你们平时也见过无数次了。
此任务是由android插件所提供的,编译、合并、打包一条龙的总线任务。平时咱们点击运行按钮、打包apk时。也是经过的调用此任务进行打包。打包后经过内置的adb命令将apk发送到手机并执行安装。
这个任务有个很重要的特性。这里我称之为按需加载特性
打个比方:假如咱们使用的组件化开发模式,项目依赖链以下图所示:
上图所示的依赖链,对组件化不熟的可能会比较懵逼。对组件化有兴趣的能够去这里了解一下组件化的项目结构:聚美组件化实践之路
这里有三个可运行的壳工程。其各自壳工程的依赖链以下:
而按需加载特性是指:在进行打包任务过程当中,打包任务只会触发当前自身依赖链中的module进行编译。而不会对别的非自身依赖链中的module进行编译。
因此,当你运行app shell1的时候。这个时候会参与打包编译的就是[app shell 1]、[component 1]、[base library]这三个module. 这就是按需加载特性
基于以上分析,我创建了此Speedup插件。利用gradle脚本,方便的进行本地aar打包发布,并经过对打包任务流程进行监听,动态的将module依赖替换为本地仓库中的maven依赖。
这里我画了个简单的流程图。便于直观的理解此gradle插件的运行机制。
在项目根目录下添加依赖并添加应用插件
buildscript {
repositories {
// 添加jitpack仓库地址
maven { url "https://jitpack.io" }
}
dependencies {
// 添加插件依赖
classpath "com.github.yjfnypeu:Speedup:0.9"
}
}
// 应用插件
apply plugin: 'speedup'
复制代码
Speedup支持配置三种属性,均配置于项目根目录下的local.properties文件中。
speedup.enable:
是否激活speedup插件。默认为false,即不激活。这样作的目的是为了使得在发版机器上进行打包apk时。自动忽略speedup插件。进行全量编译
localRepo:
本地maven仓库的地址。默认为项目根目录下的_repo文件夹。若你须要使用别的地址。在此配置个本地地址便可
excludeModules:
因为咱们开发的业务线的不一样。不少时候咱们是须要对部分的module每次都进行即时编译的:好比说如今正在作的功能。是须要对某个lib进行频繁修改的。因此这个时候。就须要使用此属性。指定此lib不须要进行加速。那么每次运行时。都会对此lib进行编译。
把全部属性全放置于local.properties中,出于如下几点考虑:
github上我提供了一个组件化demo地址, 此demo中有添加此插件配置使用。如下内容建议结合demo进行查看。
因为本地配置是放置于local.properties文件当中。因此默认依赖下来是没有开启激活此插件的。能够参考下方的配置:放入自身的local.properties中去。
speedup.enable=true
# 当须要排除多个module时,中间用英文的逗号隔开
excludeModules=:usercenter:componentusercenter
复制代码
当配置speedup.enable为true,而且同步完成以后。你就能够在gradle任务列表中发现一组speedup任务:
能够看到。speedup任务组中。含有大量的uploadXXX任务提供使用。这些任务都是在同步时根据各个library module自动生成的上传任务。主要目的是将本地的library module方便的进行打包、编译。并发布到本地的仓库中去。提供使用。
当你使用upload进行本地打包发布后,你就能够在项目根目录下的_repo文件夹下找到对应的打包出来的aar:
而后,你能够试试直接运行。而且观察右下角的Gradle Console控制台输出日志。注意看全部执行的任务列表。就会发现:执行的gradle任务明显减小了,而且被打包到本地中的module。并无被再次进行编译。
这是由于已经在运行时。动态的将对应的module替换为使用本地仓库中的aar地址了。
以上便是此插件的整个用法示例。能够总结为如下几步:
Speedup插件任务中,很重要的一点便是生成的upload任务列表了。此upload任务主要分为三类:
uploadAll
做用:用于对项目中全部的library(除了excludeModules所指定排除的module)进行打包发布。此任务默认将会对项目下全部的module执行clean操做。因此能够保证打包出来的aar是不受数据污染的
使用场景:在进行分支切换后、或者进行合并代码后。此时不少module的数据都有修改。可使用此任务一次性所有从新打包上传。
uploadForClean
做用:用于触发项目下全部module的clean任务。将其build文件夹删除。避免打包时出现数据污染。
与AS自带的clean任务不一样。自带的clean任务附带了不少额外的任务,因此每次clean会很慢。而uploadForClean。只会触发全部module自身的clean任务,对自身的build文件夹进行删除,并没有其余额外操做。这样clean的速度会获得很大提高。
此任务通常来讲外部不须要直接使用。主要是内部直接提供给uploadAll进行使用
uploadXXX
做用:用于对指定的module进行从新打包发布。好比uploadbaselib。此任务表明对baselib从新进行打包发布。