一,需求布景:

APP发布到市场后,难免会遇到严峻的BUG阻止用户运用,因此有在不发布新版别APP的情况下运用热更新技能立即批改BUG需求。原生APP(例如:Android & IOS)的热更新需求现已比较成熟,但Flutter技能栈现在还短少类似的技能方案,因此Flutter研制团队,也需求类似的热更新技能。

二,Flutter热更新技能方向分析:

通过分析现在可能有三种可行的方案: 1)类似RN结构; 2)页面动态组件结构; 3)Dart虚拟机定制方案;

方案称谓 原理 长处 缺点 开源方案
类似RN的方案 用JS以Flutter语法写dart,然后用JavaScript把XML DSL转为Flutter的原子widget组件,然后再让Flutter来烘托 因为ios系统内置支撑js,ios上完全可以完结更新 1)因为跨言语实行,关于功用有影响;学习本钱高 2)Android 端需求额外引入JS库 手Q的MXFlutter,58同城的Fair
页面动态组件方案 编译期时插桩/预埋好DynamicWidget到代码中,然后动态下发Json 数据,通过协定好的语义匹配到JSON内的数据,动态替换Widget内容来完结更新 能支撑Android/iOS 两头的更新 1)UI更新相对较简略,业务逻辑动态化较费事; 2)语义解析器开发本钱相对较大,且不易维护 3)需求一整套前后端服务和东西 天猫的Tangram,淘宝的DinamicX等
Dart虚拟机定制方案 通过分析Dart虚拟机的原理,批改Flutter Engine层Java/C++代码完结热更新的方针; 功用影响小,动态性很高,技能上可以替换全部Flutter页面(包括UI,逻辑,资源文件) 因为运用的是定制引擎,需求维护不同版别的Flutter引擎代码; 未开源

因为其他办法都有开源的示例,本案将关键以第三种“Dart虚拟机定制方案”为方针,做方案的研讨说明。

三,预备知识

在开端了解技能方案之前,需求提前了解一些相应的技能概念:

3.1 Flutter编译方式

Flutter开发言语是Dart,它的编译方式来自Dart的编译方式,主要有JIT(Just In Time)和AOT(Ahead Of Time)。

编译方式称谓 特征 长处 缺点
JIT 即时编译,典型比方V8,它可以即时编译运转JS,只需求输入源代码字符串,就可以编译运转代码 可以动态下发和实行代码,不必管CPU架构,可以提供动态化内容 1,很多字符串代码让JIT编译器花费时间和内存; 2,功用欠好;
AOT 预先编译,典型比方C/C++,通过GCC编译成二进制代码,然后装置取得权限后才可以加载实行 事前编译好的,加载和实行速度快 1,编译时差异CPU架构; 2,生成的二进制代码包比较大; 3,二进制代码需求取得权限才可以实行,无法在ios系统上动态更新

Flutter编译方式有:Debug,Release,Profile;

Flutter编译方式 特征
Debug 对应JIT方式,支撑设备和模拟器; 翻开了断言,支撑快速开发,支撑HotReload; 并未对包巨细,实行速度做优化;
Release 对应AOT方式,支撑真机,不支撑模拟器; 制止了全部断言调试信息; 对包巨细,发起和实行速度进行了优化;
Profile 类似Release方式,保留了一些调试功用,协助功用分析;

3.2 Flutter编译产品分析

Flutter下的iOS/Android工程本质上是一个规范的iOS/Android的工程;IOS途径: Flutter通过在BuildPhase中添加shell(xcode_backend.sh)来生成和嵌入App.framework和Flutter.framework到ios; Android途径: Flutter通过gradle来添加flutter.jar和编译完的二进制文件添加到Android;

3.2.1 引擎层结构分析:

Flutter热更新技能探求 | 京东云技能团队

3.2.2 Android编译产品的分析

Flutter热更新技能探求 | 京东云技能团队

Flutter热更新技能探求 | 京东云技能团队

3.2.3 IOS编译产品的分析

Flutter热更新技能探求 | 京东云技能团队

Flutter热更新技能探求 | 京东云技能团队

四,热更新技能方案分析

4.1 业务代码分析

根据“3.3.1” ~“3.3.2”的分析可以确定无论是IOS仍是Android APP业务代码都是由四个段组成:kDartVmSnapshotData、kDartVmSnapshotInstructions、kDartIsolateSnapshotData、kDartIsolateSnapshotInstructions;理论上只需能动态替换加载的代码段&数据段代码即可完结方针。

称谓 注释 作用 注释
kDartIsolateSnapshotData Dart isolate数据段 类信息,全局变量,函数指针等 容许动态下发
kDartIsolateSnapshotInstructions Dart isolate指令段 包含由Dart isolate实行的AOT代码 IOS不容许动态下发
kDartVmSnapshotData vm isolate数据段 isolate 之间同享的 Dart 堆 (heap) 的初始情况 容许动态下发
kDartVmSnapshotInstructions vm isolate指令段 包含 VM 中全部 Dart isolate 之间同享的通用程序的 AOT 指令 IOS不容许动态下发

注释: isolate, snapshot, vm isolate意义解释如下:

称谓 意义
isolate Dart是单线程,isolate跟线程差不多,可以理解为 Dart 中的线程。 isolate 与线程的差异:线程与线程之间是同享内存的,而 isolate 和 isolate 之间是内存不同享的。 不存在锁竞赛问题,两个Isolate完全是两条独立的实行线,且每个Isolate都有自己的工作循环,它们之间只能通过发送消息通讯,所以它的资源开销低于线程。
snapshot 将类信息、全局变量、函数指令直接以序列化的办法存在磁盘中,称为 Snapshot(快照)。
vm isolate 同一个进程里可以有许多isolate,但两个 isolate 的堆区是不能同享的,所以官方规划了 VM isolate,也便是 kDartVmSnapshot,用来多个 isolate 之间的交互。

Flutter热更新技能探求 | 京东云技能团队

4.2 业务代码的加载分析(运转时)

依照4.1的分析思路,咱们首要需求了解Flutter运转时代码加载的完整流程,通过梳理分析流程如下:

1 )Android- APP业务代码的加载流程:

Flutter热更新技能探求 | 京东云技能团队

2)IOS- APP业务代码的加载流程:

Flutter热更新技能探求 | 京东云技能团队

4.3 业务代码的编译生成(编译时)

根据以上的分析,咱们知道了Flutter业务代码的数据结构,也知道了在运转时怎么加载,因此咱们只需求在编译时做更改,产生自己需求的代码段,和数据段文件。在运转时加载自己的构建产品即可抵达方针。

1)在此以 IOS 构建自己的业务代码流程做详细分析:

Flutter热更新技能探求 | 京东云技能团队

**有完结构建流程可以分析,基本流程是“Dart Code(业务代码)” -> (通过Dart编译器gen_snapshot.cc) 生成 snapshot_assemble.S 的汇编文件 -> (通过xcrun东西)生成 snapshot_assemble.o的obj文件 -> (通过xcun clang东西链) 生成了 App.Framework。

2)Android的产品构建流程和IOS类似。因为Android有其他更简略的方案, 因此省掉详细的构建流程分析,大致如下:

Flutter热更新技能探求 | 京东云技能团队

4.4 完结热更新的方案探求

根据上面的技能分析结果,现已可以独立生成自己的代码段,数据段文件。通过需改虚拟机底层代码的办法,也可以动态的加载运转。但因为IOS系统现在底层的系统还不能动态加载可读写的代码段数据到内存中,所以还有技能难点需求打破。但Android端有更简略的路径可以处理,因此下面以Android端为例关键分析思路,大致如下图所示:

Flutter热更新技能探求 | 京东云技能团队

由上图可以得知,Android端 热批改核心过程如下:

1, 批改Flutter Engine代码,加载指定路径的libapp.so和flutter_aasets,比方私有目录(data/data/files);

2, 编译APK时,使用Gradle Transform插件,根据Flutter SDK的engine version动态替换官方的Flutter engine,毕竟写入批改后的engine到APK;

3, 生成补丁包:使用BSdiff算法比较新旧APK文件,生成patch补丁包

4, APP发起时访问后端接口,根据参数(app的版别号,补丁包版别号,md5,flutter SDK版别号,Engine版别号)拉取补丁包;

5, 组成补丁包:校验md5,app版别号,补丁版别号,装置时间;

6, 自定义Flutter Engine加载指定路径的libapp.so和flutter_assets资源文件;

作者:京东科技 刘振中、周智

内容来历:京东云开发者社区