Flutter热更新技术探索 | 京东云技术团队

京东云开发者
• 阅读 473

一,需求背景:

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资源文件;

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

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

点赞
收藏
评论区
推荐文章
浩浩 浩浩
3年前
Flutter 2.0 下混合开发浅析
多余的前言Flutter2.0发布时,其中最受大家关注之一的内容就是AddtoApp相关的更新,因为除了热更新之外,Flutter最受大家诟病的就是混合开发体验不好。为什么不好呢?因为Flutter的控件渲染直接脱离了原生平台,也就是无论页面堆栈和渲染树都独立于平台运行,这固然给Flutter带来了较好的跨平台体验
Karen110 Karen110
3年前
【前端自动化】如何使用Node.js实现热重载页面
前言前不久我结合browsersyncgulpgulpnodemon实现了一款生产环境热更新(我之前理解有点偏差,应该定义为热更新,不是热重载)的项目脚手架,那么,今天我们将使用Node.js实现一个热重载页面。那么,我今天就总结一下吧,以防止大家也跟我一样。热重载所谓热重载就是页面每次改动,不需要手动去刷新,可自动刷新。热更新浏览器的无刷新更新,允许在
Wesley13 Wesley13
3年前
unity热更(一)
Agenda•  什么是热更新•  为何要热更新•  如何在iOS 上对Unity 应用进行热更新•  支持UnityiOS 热更新的各种Lua 插件的对比什么是热更新• 广义定义• 无需关闭服务器,不停机状态下修复漏洞,更新资源等,重点是更新逻辑代码。• 狭义定义(iOS热更新)• 无需将代码重新打包提交至Ap
Stella981 Stella981
3年前
H5 App实现热更新,不需要重新安装app
直接上代码吧,你竟然搜到了我的文章就应该知道了,为什么要热更新//app热更新下载//假定字符串的每节数都在5位以下functiontoNum(a){//也可以这样写varca.split(/\./);varca.split('.');varnum_place""
Stella981 Stella981
3年前
Android&Flutter混合开发初体验
最近flutter不是一般的火呀,但对于一些成熟的产品来说,完全摒弃原有App的历史沉淀,全面转向Flutter是不现实的。因此使用Flutter去统一Android、iOS技术栈,把它作为已有原生App的扩展能力,通过有序推进来提升移动端的开发效率(1)创建flutter模块,创建module后会AS会自动进行flutter的相关配置!在这里
可莉 可莉
3年前
10分钟读懂阿里巴巴高级专家在Flutter Live2018的分享
作者:闲鱼技术宗心12月4日,googleflutter团队宣布第一个flutter正式版本发布。次日,FlutterLiveBeijing会议上,googleflutter团队邀请了在这一技术方案中重要的合作伙伴闲鱼团队分享这半年以来的通过flutter产出的业务结果以及对应的技术挑战。!(https://oscimg.oschin
Stella981 Stella981
3年前
DStack
混合开发这项技术由来已久,目前市面上主流的有Hybird,ReactNative,Weex,Flutter等。其中,Flutter以他独有的实现方式,优秀的性能,成为近两年最火的混合开发方案,我们学而思网校1v1客户端团队也是比较早的开始了Flutter技术的研究,在学而思网校1v1家长端和学而思网校1v1教师端两个App进行了大规模的实践尝试,由此也沉淀出
Spring Loaded代码热更新实践和原理分析 | 京东云技术团队
本文将深入探讨如何利用SpringLoaded热更新技术提高开发效率,减少编译和重启时间。分析SpringLoaded的热更新原理,以及实际应用过程中所需的操作和注意事项。
京东云开发者 京东云开发者
11个月前
热更新适配ibatis原理浅析
一、热更新解决了什么问题?在研发过程中,每个研发同学在联调、自测阶段中总会频繁的去执行编译、构建、打包的动作,遇到比较大的项目,执行一套流程下来,往往需要310分钟左右,极大的降低了研发的速度,基于以上痛点,我们基于JAVAAgent技术开发出一套插件【藏