來(lái)源 | OSCHINA 社區(qū)
作者 | 京東云開(kāi)發(fā)者-京東科技 劉振中、周智
一,需求背景:
APP 發(fā)布到市場(chǎng)后,難免會(huì)遇到嚴(yán)重的 BUG 阻礙用戶(hù)使用,因此有在不發(fā)布新版本 APP 的情況下使用熱更新技術(shù)立即修復(fù) BUG 需求。原生 APP(例如:Android & IOS)的熱更新需求已經(jīng)比較成熟,但 Flutter 技術(shù)棧目前還缺少類(lèi)似的技術(shù)方案,因此 Flutter 研發(fā)團(tuán)隊(duì),也需要類(lèi)似的熱更新技術(shù)。
二,F(xiàn)lutter 熱更新技術(shù)方向分析:
經(jīng)過(guò)分析目前可能有三種可行的方案:1)類(lèi)似 RN 框架;2)頁(yè)面動(dòng)態(tài)組件框架;3)Dart 虛擬機(jī)定制方案;
方案名稱(chēng) | 原理 | 優(yōu)點(diǎn) | 缺點(diǎn) | 開(kāi)源方案 |
---|---|---|---|---|
類(lèi)似 RN 的方案 | 用 JS 以 Flutter 語(yǔ)法寫(xiě) dart,然后用 JavaScript 把 XML DSL 轉(zhuǎn)為 Flutter 的原子 widget 組件,然后再讓 Flutter 來(lái)渲染 | 由于 ios 系統(tǒng)內(nèi)置支持 js,ios 上完全可以實(shí)現(xiàn)更新 | 1) 由于跨語(yǔ)言執(zhí)行,對(duì)于性能有影響;學(xué)習(xí)成本高 2) Android 端需要額外引入 JS 庫(kù) | 手 Q 的 MXFlutter,58 同城的 Fair |
- | - | - | - | - |
頁(yè)面動(dòng)態(tài)組件方案 | 編譯期時(shí)插樁 / 預(yù)埋好 DynamicWidget 到代碼中,然后動(dòng)態(tài)下發(fā) Json 數(shù)據(jù),通過(guò)協(xié)定好的語(yǔ)義匹配到 JSON 內(nèi)的數(shù)據(jù),動(dòng)態(tài)替換 Widget 內(nèi)容來(lái)實(shí)現(xiàn)更新 | 能支持 Android/iOS 兩端的更新 | 1)UI 更新相對(duì)較容易,業(yè)務(wù)邏輯動(dòng)態(tài)化較麻煩;2)語(yǔ)義解析器開(kāi)發(fā)成本相對(duì)較大,且不易維護(hù) 3)需要一整套前后端服務(wù)和工具 | 天貓的 Tangram,淘寶的 DinamicX 等 |
Dart 虛擬機(jī)定制方案 | 通過(guò)分析 Dart 虛擬機(jī)的原理,修改 Flutter Engine 層 Java/C++ 代碼實(shí)現(xiàn)熱更新的目標(biāo); | 性能影響小,動(dòng)態(tài)性很高,技術(shù)上可以替換所有 Flutter 頁(yè)面(包括 UI,邏輯,資源文件) | 由于使用的是定制引擎,需要維護(hù)不同版本的 Flutter 引擎代碼; | 未開(kāi)源 |
因?yàn)槠渌绞蕉加虚_(kāi)源的示例,本案將重點(diǎn)以第三種 “Dart 虛擬機(jī)定制方案” 為目標(biāo),做方案的研究講解。
三,預(yù)備知識(shí)
在開(kāi)始了解技術(shù)方案之前,需要提前了解一些相應(yīng)的技術(shù)概念:
3.1 Flutter 編譯模式
Flutter 開(kāi)發(fā)語(yǔ)言是 Dart,它的編譯模式來(lái)自 Dart 的編譯模式,主要有 JIT (Just In Time) 和 AOT (Ahead Of Time)。
編譯模式名稱(chēng) | 特點(diǎn) | 優(yōu)點(diǎn) | 缺點(diǎn) |
---|---|---|---|
JIT | 即時(shí)編譯,典型例子 V8,它可以即時(shí)編譯運(yùn)行 JS,只需要輸入源代碼字符串,就可以編譯運(yùn)行代碼 | 可以動(dòng)態(tài)下發(fā)和執(zhí)行代碼,不用管 CPU 架構(gòu),可以提供動(dòng)態(tài)化內(nèi)容 | 1, 大量字符串代碼讓 JIT 編譯器花費(fèi)時(shí)間和內(nèi)存;2, 性能不好; |
- | - | - | - |
AOT | 預(yù)先編譯,典型例子 C/C++,通過(guò) GCC 編譯成二進(jìn)制代碼,然后安裝取得權(quán)限后才可以加載執(zhí)行 | 事先編譯好的,加載和執(zhí)行速度快 | 1, 編譯時(shí)區(qū)分 CPU 架構(gòu);2, 生成的二進(jìn)制代碼包比較大;3, 二進(jìn)制代碼需要取得權(quán)限才可以執(zhí)行,無(wú)法在 ios 系統(tǒng)上動(dòng)態(tài)更新 |
Flutter 編譯模式有:Debug,Release,Profile;
Flutter 編譯模式 | 特點(diǎn) |
---|---|
Debug | 對(duì)應(yīng) JIT 模式,支持設(shè)備和模擬器;打開(kāi)了斷言,支持快速開(kāi)發(fā),支持 HotReload;并未對(duì)包大小,執(zhí)行速度做優(yōu)化; |
- | - |
Release | 對(duì)應(yīng) AOT 模式,支持真機(jī),不支持模擬器;禁止了所有斷言調(diào)試信息;對(duì)包大小,啟動(dòng)和執(zhí)行速度進(jìn)行了優(yōu)化; |
Profile | 類(lèi)似 Release 模式,保留了一些調(diào)試功能,幫助性能分析; |
3.2 Flutter 編譯產(chǎn)物分析
Flutter 下的 iOS/Android 工程本質(zhì)上是一個(gè)標(biāo)準(zhǔn)的 iOS/Android 的工程;IOS 平臺(tái): Flutter 通過(guò)在 BuildPhase 中添加 shell (xcode_backend.sh) 來(lái)生成和嵌入 App.framework 和 Flutter.framework 到 ios; Android 平臺(tái): Flutter 通過(guò) gradle 來(lái)添加 flutter.jar 和編譯完的二進(jìn)制文件添加到 Android;
3.2.1 引擎層結(jié)構(gòu)分析:
3.2.2 Android 編譯產(chǎn)物的分析
3.2.3 IOS 編譯產(chǎn)物的分析
四,熱更新技術(shù)方案分析
4.1 業(yè)務(wù)代碼分析
根據(jù) “3.3.1” ~“3.3.2” 的分析可以確定無(wú)論是 IOS 還是 Android APP 業(yè)務(wù)代碼都是由四個(gè)段組成:kDartVmSnapshotData、kDartVmSnapshotInstructions、kDartIsolateSnapshotData、kDartIsolateSnapshotInstructions;理論上只要能動(dòng)態(tài)替換加載的代碼段 & 數(shù)據(jù)段代碼即可實(shí)現(xiàn)目標(biāo)。
名稱(chēng) | 注釋 | 作用 | 注釋 |
---|---|---|---|
kDartIsolateSnapshotData | Dart isolate 數(shù)據(jù)段 | 類(lèi)信息,全局變量,函數(shù)指針等 | 允許動(dòng)態(tài)下發(fā) |
- | - | - | - |
kDartIsolateSnapshotInstructions | Dart isolate 指令段 | 包含由 Dart isolate 執(zhí)行的 AOT 代碼 | IOS 不允許動(dòng)態(tài)下發(fā) |
kDartVmSnapshotData | vm isolate 數(shù)據(jù)段 | isolate 之間共享的 Dart 堆 (heap) 的初始狀態(tài) | 允許動(dòng)態(tài)下發(fā) |
kDartVmSnapshotInstructions | vm isolate 指令段 | 包含 VM 中所有 Dart isolate 之間共享的通用程序的 AOT 指令 | IOS 不允許動(dòng)態(tài)下發(fā) |
注釋?zhuān)篿solate, snapshot, vm isolate 含義解釋如下:
名稱(chēng) | 含義 |
---|---|
isolate | Dart 是單線(xiàn)程,isolate 跟線(xiàn)程差不多,可以理解為 Dart 中的線(xiàn)程。isolate 與線(xiàn)程的區(qū)別:線(xiàn)程與線(xiàn)程之間是共享內(nèi)存的,而 isolate 和 isolate 之間是內(nèi)存不共享的。不存在鎖競(jìng)爭(zhēng)問(wèn)題,兩個(gè) Isolate 完全是兩條獨(dú)立的執(zhí)行線(xiàn),且每個(gè) Isolate 都有自己的事件循環(huán),它們之間只能通過(guò)發(fā)送消息通信,所以它的資源開(kāi)銷(xiāo)低于線(xiàn)程。 |
- | - |
snapshot | 將類(lèi)信息、全局變量、函數(shù)指令直接以序列化的方式存在磁盤(pán)中,稱(chēng)為 Snapshot(快照)。 |
vm isolate | 同一個(gè)進(jìn)程里可以有很多 isolate,但兩個(gè) isolate 的堆區(qū)是不能共享的,所以官方設(shè)計(jì)了 VM isolate,也就是 kDartVmSnapshot,用來(lái)多個(gè) isolate 之間的交互。 |
4.2 業(yè)務(wù)代碼的加載分析(運(yùn)行時(shí))
按照 4.1 的分析思路,我們首先需要了解 Flutter 運(yùn)行時(shí)代碼加載的完整流程,經(jīng)過(guò)梳理分析流程如下:
1 )Android- APP 業(yè)務(wù)代碼的加載流程:
2)IOS- APP 業(yè)務(wù)代碼的加載流程:
4.3 業(yè)務(wù)代碼的編譯生成(編譯時(shí))
根據(jù)以上的分析,我們知道了 Flutter 業(yè)務(wù)代碼的數(shù)據(jù)結(jié)構(gòu),也知道了在運(yùn)行時(shí)如何加載,因此我們只需要在編譯時(shí)做更改,產(chǎn)生自己需要的代碼段,和數(shù)據(jù)段文件。在運(yùn)行時(shí)加載自己的構(gòu)建產(chǎn)物即可達(dá)到目標(biāo)。
1)在此以 IOS 構(gòu)建自己的業(yè)務(wù)代碼流程做詳細(xì)分析:
** 有完成構(gòu)建流程可以分析,基本流程是 “Dart Code(業(yè)務(wù)代碼)” -> (通過(guò) Dart 編譯器 gen_snapshot.cc) 生成 snapshot_assemble.S 的匯編文件 -> (通過(guò) xcrun 工具) 生成 snapshot_assemble.o 的 obj 文件 -> (通過(guò) xcun clang 工具鏈) 生成了 App.Framework。
2)Android 的產(chǎn)物構(gòu)建流程和 IOS 類(lèi)似。由于 Android 有其他更簡(jiǎn)單的方案, 因此省略詳細(xì)的構(gòu)建流程分析,大致如下:
4.4 實(shí)現(xiàn)熱更新的方案探索
根據(jù)上面的技術(shù)分析結(jié)果,已經(jīng)可以獨(dú)立生成自己的代碼段,數(shù)據(jù)段文件。通過(guò)需改虛擬機(jī)底層代碼的方式,也可以動(dòng)態(tài)的加載運(yùn)行。但由于 IOS 系統(tǒng)目前底層的系統(tǒng)還不能動(dòng)態(tài)加載可讀寫(xiě)的代碼段數(shù)據(jù)到內(nèi)存中,所以還有技術(shù)難點(diǎn)需要突破。但 Android 端有更簡(jiǎn)單的路徑可以解決,因此下面以 Android 端為例重點(diǎn)分析思路,大致如下圖所示:
由上圖可以得知,Android 端 熱修復(fù)核心步驟如下:
1, 修改 Flutter Engine 代碼,加載指定路徑的 libapp.so 和 flutter_aasets,比如私有目錄 (data/data/files);
2, 編譯 APK 時(shí),利用 Gradle Transform 插件,根據(jù) Flutter SDK 的 engine version 動(dòng)態(tài)替換官方的 Flutter engine,最終寫(xiě)入修改后的 engine 到 APK;
3, 生成補(bǔ)丁包:利用 BSdiff 算法比較新舊 APK 文件,生成 patch 補(bǔ)丁包
4, APP 啟動(dòng)時(shí)訪(fǎng)問(wèn)后端接口,根據(jù)參數(shù)(app 的版本號(hào),補(bǔ)丁包版本號(hào),md5,flutter SDK 版本號(hào),Engine 版本號(hào))拉取補(bǔ)丁包;
5, 合成補(bǔ)丁包:校驗(yàn) md5,app 版本號(hào),補(bǔ)丁版本號(hào),安裝時(shí)間;
6, 自定義 Flutter Engine 加載指定路徑的 libapp.so 和 flutter_assets 資源文件;
-
Android
+關(guān)注
關(guān)注
12文章
3962瀏覽量
129525 -
開(kāi)源
+關(guān)注
關(guān)注
3文章
3582瀏覽量
43464 -
iOS
+關(guān)注
關(guān)注
8文章
3399瀏覽量
152499 -
BUG
+關(guān)注
關(guān)注
0文章
156瀏覽量
15953 -
flutter
+關(guān)注
關(guān)注
0文章
13瀏覽量
530
原文標(biāo)題:Flutter熱更新技術(shù)探索
文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
探索設(shè)計(jì)稿自動(dòng)生成Flutter代碼的技術(shù)方案

鴻蒙Flutter實(shí)戰(zhàn):07混合開(kāi)發(fā)
鴻蒙Flutter實(shí)戰(zhàn):10-常見(jiàn)問(wèn)題集合
鴻蒙Flutter實(shí)戰(zhàn):11-使用 Flutter SDK 3.22.0
鴻蒙Flutter實(shí)戰(zhàn):14-現(xiàn)有Flutter 項(xiàng)目支持鴻蒙 II
深入理解flutter的編譯原理與優(yōu)化
臺(tái)積電又在探索哪些新技術(shù)?

Flutter 3現(xiàn)已推出,能穩(wěn)定支持macOS和Linux
關(guān)于Google Flutter 3更新內(nèi)容
Flutter Forward 活動(dòng)即將到來(lái)!
與 Flutter 共創(chuàng)未來(lái) | Flutter Forward 活動(dòng)精彩回顧
Flutter圖片是如何加載的?使用過(guò)程中有哪些需要注意的地方?

了解 Flutter 3.16 功能更新

淺談兼容 OpenHarmony 的 Flutter

評(píng)論