Freeline-Android平台上的秒编译方案使用与总结

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 在以下几种情况下会自动进行全量编译:

  1. 发现 AndroidManifest.xml 有修改
  2. 发现 build.gradle 文件有修改
  3. 发现有超过 20 个 Java 文件有修改过
  4. 每次clean之后也会进行全量编译
  5. 使用AS自带的RUN之后,在使用freeline需进行一次全量编译
  6. 资源文件(res/values下的资源文件)更新(不支持删除带id的资源文件)
  7. 更新第三方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,目前还没得到解决。希望官网能尽快回复

你可能感兴趣的:(Freeline-Android平台上的秒编译方案使用与总结)