Freeline原理
Freeline是蚂蚁聚宝团队为Android平台量身定做的HotSwap方案。它的技术思想来源于Buck和LayoutCast,并做了改良。Freeline全版本覆盖,2.x ~ 6.x版本均支持;平台覆盖也比Buck(PC端不支持Windows)和LayoutCast(手机端不支持Android 5.0以下)广。
工作流程:PC端与手机建立TCP长连接,扫描各个子工程文件变化,各个子工程的增量dex构建,增量资源包构建,合并所有工程dex,传输增量包。
增量更新主要分为代码增量和资源增量。
代码增量
在代码增量方面,Freeline采用的是主流Hotpatch的方案:植入Dex 到系统DexList。在Google支持MultiDex后,构建工具默认会按照65536方法及LinearAlloc内存限制进行分包,一般一个大型app,会有多个dex文件存在。系统从dex数组最前的位置开始找,找到对应的Class则不会继续往下找。在应用启动时候,把我们准备好的增量dex通过反射注入到DexElements最前面,则整个增量部署就完成了。
资源增量
资源增量是Freeline相对其他构建方式,比较明显的一个特性。资源增量主要需要解决下面三个问题:
- 增量包资源id怎么兼容基线包资源id?
- 怎么样高效构建出仅仅包含变更集合的资源包?
- 怎么样在手机端让上面构建的增量包生效?
解决第一个问题,Freeline采取的思路是通过最后一次编译res过程的R.java,反向导出保留id所需要的两个文件(public.xml,ids.xml),这个功能抽成单独的工具“id-gen-tool”,该工具会根据枚举常量生成的id的上下文特征,过滤掉枚举常量,解决掉其引起的内存越界问题。
剩下两个问题,可以阅读下面的参考资料,内有详细说明。
缺点
Freeline也并非没有缺点,它有以下几点限制:
- 第一次增量资源编译的时候可能会有点慢
- 不支持删除带 id 的资源,否则可能导致 aapt 编译出错
- 暂不支持抽象类的增量编译
- 不支持开启 Jack 编译
- 不支持 Kotlin/Groovy/Scala
Freeline集成
Freeline选择Python+Java作为构建语言,因此需要安装Python环境,并添加到环境变量中。阅读freeline源码,可以发现目前只支持Python 2.7+,对Python 3.0及以上版本不支持。
1 | def main(): |
配置 project-level 的 build.gradle,加入 freeline-gradle 的依赖:
1 | buildscript { |
然后,在你的主 module 的 build.gradle 中,应用 freeline 插件的依赖:
1 | apply plugin: 'com.antfortune.freeline' |
最后,在命令行执行以下命令来下载 freeline 的 python 和二进制依赖。
Windows[CMD]: gradlew initFreeline
Linux/Mac: ./gradlew initFreeline
Freeline 最快捷的使用方法就是直接安装 Android Studio插件,此外也可以通过python命令1
2
3
4
5
6
```Dos
freeline {
hack true
productFlavor 'product_hemu'
}
在使用Freeline后,freeline 在全量编译后,会自动进行增量编译,但是在以下几种情况下,会从增量编译转入全量编译:
- 涉及到 build.gradle、settings.gradle、AndroidManifest.xml 文件的改动
- 增量编译时,发现有超过20个java 文件出现改动
##JRebel for Android原理
JRebel是一款Java热更新插件,最早使用在Java Web以及Java Server端的开发中。它支持所有的JVM语言,比如Java,Groovy以及Scala等;同时支持多个IDE,比如Eclipse,MyEclipse以及 IntelliJ IDEA等。
为了可以在运行期间更新项目代码,需要运行classes文件并在APK中添加代理。代理用于接收变更过的类以及资源。为了减少启动时间,Jrebel在在Gradle Plugin中增加了一个jrebelPrepareDebug任务,但是跳过dexing这个过程。因此构建APK不包括任何.dex文件,但是包括所有相关的APK文件:manifest,resources,.so库等等。一旦这个加壳APK安装完成,所有运行过的项目代码会被发送到代理那里,然后程序就会启动。
如果代码或者资源有变化,点击”Apply changes with JRebel for Android”(安装插件后会出现)按钮,就会启用jrebelCompileDebug这个Gradle task。所有有改变的类和资源会被打包然后通过ADB发送给代理。代理会应用这些变更资源。为了确保app使用的是最新的资源,代理会调用任务栈里top-most activity的recreate方法。通常在设备配置改变后(比如转动设备)才会调用这个方法。
JRebel使用
JRebel For Android的使用非常简单,只要在Plugin里搜索并且安装就可以了。此外它还支持Debuger模式(Freeline不支持)。
使用感受
使用Freeline全量更新Apk,记录数据如下:
次数 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
启动时间 | 181s | 145s | 195s | 211s |
删除了一段代码后重新部署耗时7s,修改资源名后重新部署耗时3s,感觉速度还算快。但是前期集成有点麻烦,而且在使用Freeline后切回AS自带的运行方式,需要先clean一把。
在速度上JRebel和Freeline差不多,但是使用比较简单,而且支持debug模式,综上JRebel更胜一筹。