真當Flutter不能熱更新?衆能動態化Flutter

效果展現

上面鐵軍中的這個關於咱們頁面以及轉換爲了動態化頁面。java

動態化標籤 python

動態化路由 一個flutter頁面轉換爲動態化頁面,只須要添加動態化標籤和動態化路由就好了,對業務頁面的開發修改不多,相比其餘動態化方案是巨大的優點json

方案對比

方案名稱 美團 滿幫 衆能
簡述 dart文件編譯爲json,使用自定義運行時調用proxy方法 使用js經過自定義js虛擬機調用flutter業務組件 dart文件編譯爲lua字節碼,使用lua虛擬機調用proxy方法
開發語言 dart js dart
語法支持 不支持async和await 支持async和await
flutter控件支持 所有支持 只能使用自定義組件 所有支持
開發調試 使用dart自帶debugger 自定義debugger 使用dart自帶debugger
核心原理 使用自定義運行時解析json,調用proxy 經過自定義js虛擬機調用proxy 使用修改後的lua虛擬機調用proxy方法

三個方案都必須使用proxy方法,由於flutter中的dart閹割了反射,必須經過某種方式經過proxy方法來調用dart方法。 proxy方法以下圖,這是掃描鐵軍App自動生成的: 衆能的方案對比美團,優點在於使用了成熟的lua虛擬機的機制,在運行時執行的是指令,例如加法 會被編譯兩個loadConstant指令和一個binaryArith指令。而美團的方案核心是自定義的運行時,基本單位是語句和表達式,粒度粗了一個級別,直接的影響就是不支持async和await等異步語法。xcode

衆能的方案對比滿幫,優點在於自動支持全部的flutter組件、第三方和自定義組件,同時開發調試時是使用flutter自帶的編譯器和調試器。而滿幫方案開發時只能使用js語言,同時只能使用有限的flutter組件,有限的業務組件。緩存

核心原理比喻

衆能的方案核心其實和樂高積木同樣: 普通flutter頁面就像上面這個塑料恐龍,要改動一點必須在工廠從新生產。 使用衆能動態化的頁面,至關於使用不少個小塊的樂高積木模仿出了原始的頁面,小塊的樂高積木就是proxy方法。 因此動態化頁面實際上是高仿的頁面,和原始的頁面有些細微的不一致。 可是優點就是動態化的頁面能夠在本身在運行時修改。markdown

動態化流程1-jenkins打包

jenkins流水線在xcode編譯前加入了動態化工具下載,以及動態化編譯就是流程圖中黃色的部分。異步

動態化流程2-啓動註冊路由

每個動態化dart文件都會編譯出.out字節碼文件,但只有帶routerModel的頁面.out文件都纔要在啓動時執行生成routerModelasync

.out字節碼文件就是上圖這樣,在啓動時執行這個字節碼就會生成routerModel,而後動態化虛擬機就休眠了,直到進入動態化頁面纔會啓動。工具

這個字節碼的內容是和lua字節碼徹底一致的,甚至在項目初期真正的lua字節碼能夠在mars_vm中運行並輸出同樣的結果,python、java等虛擬機中字節碼也是相似結構,都有指令集,本地變量集合等信息。 虛擬機是另一種語言來執行目標語言的,例如lua官方虛擬機是使用c語言來執行lua,也有go語言版本的。python虛擬機有java、c、go等多個版本。 衆能的這個虛擬機是dart實現的,能夠執行lua和dart。lua

動態化流程3-進入頁面

進入頁面後就會執行路由routerModel的block,完成頁面初始化爲爲statefullWidget,並按照StatefullWidget自己的生命週期調用對應方法。

最簡單的虛擬機指令展現

動態化運行hello_world代碼,完成hello world字符串打印,這個在虛擬機裏面是比較複雜的,由於要用到包加載等功能。 最簡單的指令是算數運算指令,例以下面這個加法。

a = b + 100
複製代碼

會被編譯爲三條指令,load指令從寄存器中加載b到棧頂,load指令從常量表中加載c到棧頂, 執行算數指令把棧頂的兩個數彈出進行算數運算,結果放入a寄存器的位置。

待完善的功能點

一、目前虛擬機調試時不能和原始的dart代碼對應上,還好預留了行號信息等字段,一個月內應該能夠加上。

二、目前的命名空間實現不夠完善,同一個庫內類名不能重複。 三、調用proxy方法的指令過多,經過修改命名空間的機制,應該能夠把指令數減半。 四、沒有實現方法緩存,反覆調用同一個方法的話,會重複使用指令加載這個方法。

相關文章
相關標籤/搜索