已經好久沒有寫文章了,最近被業務折磨的一塌糊塗,跟個陀螺似的,被逆時針、順時針來回地抽/(ㄒoㄒ)/。
好久前就想捋一捋 Flutter 混開專案中熱修復的實現方式,最近在業餘時間耗費了一些精力終於實現了該功能,故在此分享下實現思路。
當前文章中的 FlutterSDK 特指 2.2.2 版本,新版本 SDK 中涉及熱修復視窗的相關程式碼發現了變化,1.X 版本的實現方式已經過時了。
實現原理
我的實現思路用到 Tinker + ASM + 自定義GradlePlugin
,Tinker 用於打資源差分包,ASM 用於編輯關鍵類的位元組碼,GradlePlugin 中使用 Transform 在 Android 專案編譯期間去使用 ASM 的位元組碼編輯功能。
在 Flutter 的早期版本中,Google 是有提供官方的熱修復能力的,但是在後期的迭代版本中又將該能力給遮蔽掉了。但是其仍然留有一個視窗給到我們去對 Flutter 程式碼與資源進行熱修復(特指Android+Flutter混開專案),只要瞭解了該視窗的具體發生時機
與 Flutter Module 構建產物
的知識,我們便可以很直觀地實現 Flutter 的熱修復功能。
-
Flutter 構建產物(release):我們只需要關注第2與3點
- libflutter.so:Flutter 引擎相關程式碼,不需要關心。
- libapp.so:Flutter Module 會編譯成該 動態庫,我們編寫的 dart 程式碼都在這裡,熱修復 Flutter 程式碼通過替換該動態庫實現。
- assets/flutter/xxx:Flutter Module 的資源位於 apk 包的 assets 下。
-
熱修復視窗:貼程式碼可能要貼很多程式碼,我這裡簡單描述下該該視窗的發生時機
-
FlutterActivity
中的委託類FlutterActivityDelegate
的onCreate
函式中,會執行 Flutter 引擎的初始化方法。 -
初始化方法會通過下述呼叫程式碼:
String[] args = getArgsFromIntent(activity.getIntent()); FlutterMain.ensureInitializationComplete(activity.getApplicationContext(), args); 複製程式碼
我們關注重點在
FlutterMain.ensureInitializationComplete()
中。- 具體實現程式碼就不展開,
FlutterMain.ensureInitializationComplete()
中會有libapp.so
動態庫的位置引數的配置與傳遞,它最終的是通過FlutterJNI.init(xxx)
函式進行初始化(注意:該libapp.so
動態庫的載入與平時的loadLibrary(String libname)
機制不同,不能簡單的使用 Tinker 進行熱修復)。 FlutterJNI.init(xxx)
函式的入參String[] args
會包含2個帶有--aot-shared-library-name=
的字串元素用於指定libapp.so
動態庫的位置,其中一個是相對位置,一個是絕對位置。相對位置定址失敗便會使用絕對位置進行定址。- 我們只需要使用 ASM + GradlePlugin 編輯
FlutterJNI.init(xxx)
函式的位元組碼,將--aot-shared-library-name=
字串元素指定為我們自定義的動態庫絕對路徑即可實現 Flutter 程式碼的熱修復。
-
實現步驟
如下
-
引入 Tinker 熱修復能力,這個沒啥好說的吧
-
對 Flutter 資源和程式碼進行修改,方便驗證。
-
開發 Gradle 外掛,使用 Transform api + ASM ,對
FlutterJNI.init(xxx)
的函式位元組碼進行編輯。 -
FlutterJNI.init(xxx)
的函式位元組碼編輯的主要做以下操作-
判斷當前應用是否有做 Tinker 熱修復,該次熱修復操作是否有下發
libapp.so
動態庫。 -
獲取
libapp.so
動態庫的絕對地址,修改字串陣列中--aot-shared-library-name=
的字串元素的值指向該絕對地址。 -
實現 Flutter 程式碼熱修復,而 Flutter 資源熱修復不需關心,Tinker 本身支援 assets 的熱修復,不需要額外處理。
-
該步驟還可以優化,外掛的開啟時機建議在只做 Flutter 熱修復的時候才開啟。
-
使用 Gradle 外掛,執行 Tinker patch 生成的 Task,安裝補丁重啟驗證。
-
按照以上步驟,本人親測可實現 Flutter 的熱修復功能(Android+Flutter混開專案)。
小結
因精力有限,文章中很多內容沒有展開描述,如有錯誤還望指出,共同進步哈。
如果你覺得本篇文章有用的話還請點贊支援下,謝謝!