Freeline 是蚂蚁金服团队开发的一款Android平台上的秒级编译方案,能够显著地提高 Android 工程的编译速度。
1.Freeline 原理?
- Freeline本质上是一个热补丁方案
- 将修改过的*.java和资源文件分别打成dex和pack,然后通过socket传输到手机上,在运行期动态加载生效。
- 其实就是热更新技术在编译期的运用,通过对同一个 apk 进行持续地热更新来达到增量编译的效果。
- 具体原理可以阅读Freeline - Android平台上的秒级编译方案。
2.谁在用?
开源至今,已有来自 BAT、新美大、今日头条、携程、聚美优品等上百款 App 使用了 Freeline 来提高工程师们的开发效率,Freeline 对轻量级到重量级的 Android 应用都提供了强有力的增量编译支持。
3.Freeline 的维护情况
Freeline 主工程目前主要由两位蚂蚁金服的工程师在维护(最近一次更新是2017/11/08),Android Studio 插件目前主要由社区开发者维护。
4.Freeline 支持的特性
- 支持标准的多模块 Gradle 工程的增量构建
- 并发执行增量编译任务
- 进程级别异常隔离机制)
- 支持 so 动态更新
- 支持 resource.arsc 缓存
- 支持 retrolambda
- 支持 DataBinding
- 支持各类主流注解库(APT)
- 支持 Windows,Linux,Mac 平台
* | Java | drawable, layout, etc. | res/values | native so |
---|---|---|---|---|
add | √ | √ | √ | √ |
change | √ | √ | √ | √ |
remove | √ | √ | x | - |
以下列表为 Freeline 支持的热更新情况:
* | Java | drawable, layout, etc. | res/values | native so |
---|---|---|---|---|
add | √ | √ | √ | √ |
change | √ | √ | √ | √ |
remove | √ | √ | x | - |
5.测试情况
测试手机:小米5c(API25)、Nexus5X(API27)模拟器(API26),三种机型测试结果一致。
freeline接入版本:0.8.8
(1)对比编译速度
未接入freeline时,编译一次大致4m 8s
使用freeline编译打包,首次运行时需要全量编译,速度会比较慢一点,在我们项目上运行了3578.0s,确实有点慢,要有点耐心才行:
除首次编译比较慢之外,再次编译就是增量编译了,速度提升很快,几乎每次都是10s内就能完成一次编译打包的过程,整个编译过程仅仅6.1s,效果还是很明显的
(2)兼容性
适用于API14以上版本,Freeline官方说明 已经分别在 API 17,19,22,23的 Android 模拟器、Android 6.0 Nexus 6P 以及 Android 4.4 锤子手机上经过测试。如果想要充分体验 Freeline 增量编译的速度的话,最好使用 Android 5.0+ 的设备。另外freeline还有一些局限性:
- 第一次增量资源编译的时候可能会有点慢,因为需要额外传递一个完整的资源包
- 不支持删除带id的资源,否则可能导致aapt编译出错
- 暂不支持抽象类的增量编译
- 部分 APT 插件可能需要单独适配
- 不支持开启 Jack 编译
- 不支持 Kotlin / Groovy / Scala等语言
- 一台设备只支持一个应用依赖freeline,多个设备只能手动选择设备
Freeline 在以下几种情况下会自动进行全量编译:
- 发现 AndroidManifest.xml 有修改
- 发现 build.gradle 文件有修改
- 发现有超过 20 个 Java 文件有修改过
- 每次clean之后也会进行全量编译
- 使用AS自带的RUN之后,在使用freeline需进行一次全量编译
- 资源文件(res/values下的资源文件)更新(不支持删除带id的资源文件)
- 更新第三方jar包的引用
6 如何接入Freeline?
接入准备
Freeline是采用Python编写的,所以我们需要安装python环境,根据网上的说法,最好使用python2.7版本(有人使用python3.5无法成功集成)。
有两种接入 Freeline 的方法,最简单的方法是通过 Android Studio 的插件来接入(实际上是对命令行的方式做了封装,提供自动化的解决方案),另一种则是手工通过修改配置与执行命令的方式来接入。
方法一:Android Studio 插件
在最新版本的 Freeline 插件中,提供了自动化一键接入的方式,不需要像以前一样手动修改build.gradle配置文件了。
在 Android Studio 中,通过以下路径:
- MacOS
Android Studio → Preferences... → Plugins → Browse repositories...
- Windows 和 Linux
File → Settings... → Plugins → Browse repositories...
搜索“freeline”,并安装。
直接点击 Run Freeline(首次运行先需要一个较为耗时的全量编译过程)。
除此之外,你也可以通过在命令行执行 Python 脚本的方式来使用 Freeline,
python freeline.py
freeline.py
使用 freeline 进行编译的主要入口,freeline 主要通过 python 来实现跨平台。
参数:
- -h
- 使用方式:python freeline.py -h
- 参数说明:输出 freeline 的参数使用说明
- -v
- 使用方式:python freeline.py -v
- 参数说明:获取 freeline.py 的版本号
- -f
- 使用方式:python freeline.py -f
- 参数说明:强制进行全量编译
- -d
- 使用方式:python freeline.py -d(注:可与各类参数叠加使用)
- 参数说明:输出 freeline 的调试日志(注意:不是对 Android 工程进行调试)
- -w
- 使用方式:python freeline.py -f -w
- 参数说明:让应用启动的时候等待调试工具连接(目前只支持全量编译的时候配合使用),日常调试推荐直接使用 Android Studio 的attach debugger to Android process
方法二:命令行方式接入
配置 project-level 的 build.gradle,加入 freeline-gradle 的依赖:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.antfortune.freeline:gradle:x.x.x'
}
}
然后,在你的主 module 的 build.gradle 中,应用 freeline 插件的依赖:
apply plugin: 'com.antfortune.freeline'
android {
...
freeline {
... // 具体的配置内容
}
}
最后,在命令行执行以下命令来下载 freeline 的 python 和二进制依赖。
Windows[CMD]: gradlew initFreeline
Linux/Mac: ./gradlew initFreeline
对于国内的用户来说,如果你的下载的时候速度很慢,你也可以加上参数,执行gradlew initFreeline -Pmirror
,这样就会从国内镜像地址来下载。
7 遇到的坑
一启动就 crash 报错 NoClassDefFoundError?
按照官网给出的修复方案:
修改一下 build.gradle 文件,添加配置项:
freeline {
...
applicationProxy false
}
在你的Application类中加入:
public class YourApplication extends Application {
public onCreate() {
super.onCreate();
FreelineCore.init(this);
}
}
然后clean,重新打包即可解决问题。
然而设置了applicationProxy属性为false时,编译的时候会出现另一个错误
python freeline.py
[INFO] preparing for tasks...
[-][connect_device_task] finished. in 10.6s
[-][gradle_aapt_task] finished. in 0.0s
[-][app] finished. in 0.0s
[-][gradle_check_mobile_change_task] finished. in 125.2s
[-][merge_dex_task] finished. in 0.0s
[-][gradle_push_history_inc_task] failed. in 0.0s
[-][gradle_sync_task] failed. in 0s
[-][gradle_backup_inc_product_task] failed. in 0s
[-][clean_cache_task] failed. in 0s
[-][update_stat_task] failed. in 0s
[ERROR] --------------------------------------------------------
[ERROR] Freeline ERROR
[ERROR] --------------------------------------------------------
[ERROR] --------------------------------------------------------
[ERROR] get sync ticket failed
[ERROR] --------------------------------------------------------
[DEBUG] Prepare tasks time: 0.2s
[DEBUG] Task engine running time: 135.8s
[DEBUG] Total time: 135.9s
[DEBUG] --------------------------------------------------------
这个问题已经在Github提了issue,目前还没得到解决。希望官网能尽快回复