在以前的一篇文章《Flutter的探索與實踐》中關於Flutter如何構建到現有項目這一節沒有詳細說,這篇文章將會介紹Flutter在混合項目中的構建和集成方面踩過的坑以及解決方案。android
扇貝現有的項目是原生混合React Native,而且是以組件化的架構存在,如今想在一些頁面上用Flutter進行重構,想要在新的Flutter項目上集成之前的全部代碼確定是不現實的,同時又不想將Flutter項目直接侵入到咱們的項目結構中去,因而咱們選擇將重構好的Flutter代碼單獨編譯成aar,以組件的形式被主工程依賴。bash
這樣作的好處是顯而易見的: 對Flutter進行探索開發的同窗能夠在本身的Flutter工程內編寫dart代碼,獨立運行調試,發佈版本的時候打包成aar集成到主工程中讓寫native代碼的同窗接入,兩方能夠協同工做,不會產生耦合。架構
下面的構建和集成是以Android項目爲例。app
首先用Android Studio或者命令行新建一個Flutter 工程。組件化
獲得以下項目結構post
在命令行輸入命令flutter build apk
會編譯生成apk文件,位於build/app/outputs/apk/release/
文件夾下。 將apk解壓縮後就能夠看到裏面的結構組成。gradle
這個apk裏的產物其實是在Android的app/build.gradle構建代碼裏引入了Flutter的構建代碼。ui
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
複製代碼
經過閱讀flutter構建源碼咱們發如今構建apk文件的時候,會將須要的文件構建到apk中。編碼
assets文件夾下面有flutter_assets文件夾、flutter_shared文件夾、isolate_snapshot_data、isolate_snapshot_instr、vm_snapshot_data、vm_snapshot_instr文件。spa
lib文件夾下是特定平臺(arm或者x86)的so文件。
flutter在Android平臺下會默認生成arm-v7架構的的so庫,flutter.gradle源碼中會根據target-platform
屬性判斷平臺動態生成對應的so,官方註釋目前flutter只支持在debug模式下生成x86的so。
扇貝應用集成了一部分三方的so庫,並且只選用了arm架構的so庫,x86的設備只佔到1%左右,所以下面的操做都是默認爲arm架構。對須要x86 so的同窗下文會作說明。
上面經過編譯命令獲得了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
文件。
咱們將獲得的aar文件集成到現有的Android工程中供native的小夥伴使用,可是打開flutter頁面卻閃退了,同時flutter報出了error,錯誤是說aar裏面缺乏icudtl.dat文件。
解壓縮aar查看文件結構,能夠發現其中的問題。
在aar文件夾下的assets裏面缺乏了flutter_shared文件夾,icudtl.dat文件正是在該文件夾裏面,也就是說flutter.gradle在編譯流程中並無將icudtl.dat文件打進aar包裏面,這一點從flutter庫的issue裏面獲得了證明,咱們的辦法是將apk裏面獲得的flutter_shared文件夾手動copy到flutter工程中,再次編譯aar,這樣就能夠獲得有icudtl.dat的aar文件。再次集成到Android項目中即可以成功運行,不會產生錯誤。這個方案須要兩個步驟,第一步是先編譯成apk取得icudtl.dat文件放入到工程中,第二步修改apply plugin: 'com.android.library'
再次編譯取得aar。