Flutter在混合專案中的構建和整合

kinsomy發表於2019-03-04

寫在前頭

在之前的一篇文章《Flutter的探索與實踐》中關於Flutter如何構建到現有專案這一節沒有詳細說,這篇文章將會介紹Flutter在混合專案中的構建和整合方面踩過的坑以及解決方案。

目標

扇貝現有的專案是原生混合React Native,並且是以元件化的架構存在,現在想在一些頁面上用Flutter進行重構,想要在新的Flutter專案上整合以前的所有程式碼肯定是不現實的,同時又不想將Flutter專案直接侵入到我們的專案結構中去,於是我們選擇將重構好的Flutter程式碼單獨編譯成aar,以元件的形式被主工程依賴。

這樣做的好處是顯而易見的:
對Flutter進行探索開發的同學可以在自己的Flutter工程內編寫dart程式碼,獨立執行除錯,釋出版本的時候打包成aar整合到主工程中讓寫native程式碼的同學接入,兩方可以協同工作,不會產生耦合。

探索過程

下面的構建和整合是以Android專案為例。

首先用Android Studio或者命令列新建一個Flutter 工程。

得到如下專案結構

Flutter在混合專案中的構建和整合

在命令列輸入命令flutter build apk
會編譯生成apk檔案,位於build/app/outputs/apk/release/資料夾下。
將apk解壓縮後就可以看到裡面的結構組成。

Flutter在混合專案中的構建和整合

這個apk裡的產物實際上是在Android的app/build.gradle構建程式碼裡引入了Flutter的構建程式碼。

apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
複製程式碼

通過閱讀flutter構建原始碼我們發現在構建apk檔案的時候,會將需要的檔案構建到apk中。

1.assets資料夾

assets資料夾下面有flutter_assets資料夾、flutter_shared資料夾、isolate_snapshot_data、isolate_snapshot_instr、vm_snapshot_data、vm_snapshot_instr檔案。

  • flutter_assets裡是flutter工程產生的assets檔案
  • flutter_shared裡是封裝在flutter.jar裡面的處理字元編碼的ICU庫
  • isolate_snapshot_data、isolate_snapshot_instr、vm_snapshot_data、vm_snapshot_instr為特定平臺的資料和指令
2.lib資料夾

lib資料夾下是特定平臺(arm或者x86)的so檔案。

flutter在Android平臺下會預設生成arm-v7架構的的so庫,flutter.gradle原始碼中會根據target-platform屬性判斷平臺動態生成對應的so,官方註釋目前flutter只支援在debug模式下生成x86的so。

Flutter在混合專案中的構建和整合

扇貝應用整合了一部分三方的so庫,而且只選用了arm架構的so庫,x86的裝置只佔到1%左右,因此下面的操作都是預設為arm架構。對需要x86 so的同學下文會做說明。

抽取aar

上面通過編譯命令得到了apk,那想要打包成aar,理論上只要把app/build.gradle中的apply plugin: `com.android.application`修改為apply plugin: `com.android.library`,同時刪除applicationId "com.shanbay.flutterapp"再次執行flutter build apk命令,便可以得到app-release.aar檔案。

Flutter在混合專案中的構建和整合

整合到現有專案

我們將得到的aar檔案整合到現有的Android工程中供native的小夥伴使用,但是開啟flutter頁面卻閃退了,同時flutter報出了error,錯誤是說aar裡面缺少icudtl.dat檔案。

Flutter在混合專案中的構建和整合

解壓縮aar檢視檔案結構,可以發現其中的問題。

Flutter在混合專案中的構建和整合

在aar資料夾下的assets裡面缺少了flutter_shared資料夾,icudtl.dat檔案正是在該資料夾裡面,也就是說flutter.gradle在編譯流程中並沒有將icudtl.dat檔案打進aar包裡面,這一點從flutter庫的issue裡面得到了證實,我們的辦法是將apk裡面得到的flutter_shared資料夾手動copy到flutter工程中,再次編譯aar,這樣就可以得到有icudtl.dat的aar檔案。再次整合到Android專案中便可以成功執行,不會產生錯誤。

Flutter在混合專案中的構建和整合
Flutter在混合專案中的構建和整合

總結

這個方案需要兩個步驟,第一步是先編譯成apk取得icudtl.dat檔案放入到工程中,第二步修改apply plugin: `com.android.library`再次編譯取得aar。

優點

  • 完全依賴flutter自己的編譯流程,不會對其原始碼進行修改,侵入flutter編譯流程,定製化的成分較少,適用於絕大部分場景,同時隨著flutter更新,需要對這套流程做修改的可能性也比較小。
  • 可以直接接入CI系統,最小修改。
  • 在android工程中可以編寫sample程式碼,通過flavor構建在release aar時移出sample程式碼,不需要另外建立host工程執行除錯。

相關文章