Flutter完整開發實戰詳解(十四、混合開發打包 Android 篇)

戀貓de小郭發表於2019-06-03

本篇將帶你深入瞭解 Flutter 中打包和外掛安裝等原理,幫你快速完成 Flutter 整合到現有 Android 專案,實現混合開發支援。

前文:

一、前言

隨著各種跨平臺框架的不斷湧現,很多時候我們會選擇混合開發模式作為腳手架 ,因為企業一般不會把業務都壓在一個框架上,同時除非是全新專案,不然出於對原有業務重構的 成本和風險 考慮,都會選擇混合開發去嘗試入坑。

但是混合開發會對 打包、構建和啟動等流程熟悉度要求較高 ,同時遇到的問題也更多,以前我在 React Native 也寫過類似的文章 :《從Android到React Native開發(四、打包流程解析和釋出為Maven庫)》 ,而這方面是有很多經驗可以通用的,所以適當的混開模式有利於避免一些問題,同時只有瞭解 Flutter 整體專案的構建思路,才有可能更舒適的躺坑。

額外嘮叨一句,跨平臺的意義更多在於解決多端邏輯的統一 ,至少避免了邏輯重複實現,所以企業剛開始,一般會選擇一些輕量級業務進行嘗試。

二、打包

一般跨平臺混合開發會有兩種選擇:

  • 1、將 Flutter 整體框架依賴和打包指令碼都整合到主專案中。
  • 2、以 aar 的完整庫整合形式新增到主專案。

兩種實現方法各有利弊:

  • 第一種方式可以更方便執行時修改問題,但是對主專案“汙染”會比較高,同時改動會大一些。

  • 第二種方式 需要單獨除錯後,更新 aar 檔案再整合到專案中除錯,但是這類整合方式更乾淨,同時 Flutter 相關程式碼可獨立執行測試,且改動較小。

一般而言,對於普通專案我是建議以 第二種方式整合到專案中的 ,通過新建一個 Flutter 工程,然後對工程進行元件化指令碼處理,讓它 既能以 apk形式單獨執行除錯,又能打包為aar形式對外提供支援。

相信對於原生平臺熟悉的應該知道,我們可以通過簡單修改專案gradle 指令碼,讓它快速支援這個能力,如下圖片所示,圖片中為省略的部分指令碼程式碼,完整版可見 flutter_app_lib

Flutter完整開發實戰詳解(十四、混合開發打包 Android 篇)

我們通過了 isLib 標記為去簡單實現了專案的打包判斷,當專案作為 lib 釋出時,設定 isLib 為 true,之後執行 ./gradlew assembleRelease 即可 ,剩下的工作依舊是 Flutter 自身的打包流程,而對於打包後的 aar 檔案直接在原生專案裡引入即可完成依賴。

而一般接入時,如果需要 token 、使用者資料等資訊,推薦提供定義好原生介面,如 init(String token, String userInfo) 等,然後通過MethodChannel 將資訊同步到 Flutter 中。

對於原生主工程,只需要接入 aar 檔案,完成初始化並開啟頁面,而無需關心其內部實現,和引入普通依賴並無區別。

你可能需要修改的還有 AndroidManifset 中的啟動 MainActivity 移除,然後新增一個自定義 Activity 去繼承 FlutterActivity 完成自定義。

三、外掛

如果普通情況下,到上面就可以完成 Flutter 的整合工作了,但是往往事與願違,一些 Flutter 外掛在提供功能時,往往是通過原生層程式碼實現的,如 flutter_webviewandroid_intentdevice_info 等等,那這些程式碼是怎麼被引用的呢?

這裡稍微提一下,用過 React Native 的應該知道,帶有原生程式碼的 React Native 外掛,在 npm 安裝以後,需要通過 react-native link命令完成安裝處理。 這個命令會觸發指令碼修改原生程式碼,從而修改 gradle 指令碼增加對外掛專案的引用,同時修改 java 程式碼實現外掛的模版引入,這使得專案在一定程度被外掛“汙染”。

React Native 中帶有原生程式碼的外掛,會被以本地 Module 工程的方式引入,那 Flutter 呢?

其實原理上 Flutter 帶有原生程式碼的外掛,在外掛安裝後,也是會以本地 Module Project 的形式引入 ,但是它整個過程更加巧妙,讓開發中對這個過程幾乎無感。

如下圖所示,不知道你注意過沒有,在外掛安裝之後,所有帶原生程式碼的外掛,都會以路徑和外掛名的key=value 形式 存在 .flutter-plugins 檔案中。

Flutter完整開發實戰詳解(十四、混合開發打包 Android 篇)

而在 android 工程的 settings.gradle 裡,如下圖所示,會通過讀取該檔案將 .flutter-plugins 檔案中的專案一個個 include 到主工程裡。

Flutter完整開發實戰詳解(十四、混合開發打包 Android 篇)

之後就是主工程裡的 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 指令碼的引入了,這個指令碼一般在於 flutterSDK/packages/flutter_tools/gradle/ 目錄下,如下程式碼所示,其中最關鍵的部分同樣是 讀取 .flutter-plugins 檔案中的專案,然後一個一個再 implementation 到主工程裡完成依賴。

Flutter完整開發實戰詳解(十四、混合開發打包 Android 篇)

自此所有原生程式碼的 Flutter 外掛,都被作為本地 Module Project 的形式引入主工程了 ,最後指令碼會自動生成一個 GeneratedPluginRegistrant.java 檔案,實現原生程式碼的引用註冊, 而這個過程對你完全是無感的。

說了那麼多就是為了說明,既然外掛是被當作本地 Module Project 的形式引入,那麼這時候按照原來直接打包 aar 是會有問題的:

`Android` 預設 `gradle` 指令碼打包時,對於 `project` 和遠端依賴只會打包引用而不會打包原始碼和資源。

所以這時候就需要 fat-aar 的加持了,關於 fat-aar 的詳細概念可見 :《從Android到React Native開發(四、打包流程解析和釋出為Maven庫)》 ,這裡可以簡單理解為,這是一個支援將引用程式碼和資源到合併到一個 aar 的外掛。

如下程式碼所示,我們在原本的元件化指令碼上,通過增加 apply plugin: 'com.kezong.fat-aar' 引入外掛,然後參考 Flutter 指令碼對 .flutter-plugins 檔案中的專案進行 embed 依賴引用即可 ,這時候再打包出的 aar 檔案即為完整 Flutter 專案程式碼。

Flutter完整開發實戰詳解(十四、混合開發打包 Android 篇)

完整版可見 flutter_app_lib

四、堆疊

最後需要說的問題就是堆疊了。

如果說混合開發中最難處理的是什麼,那一定是各平臺之間的堆疊管理,一般情況下我們都會避免混合堆疊的相互呼叫 ,但是面對不得不如此為之的情況下,閒魚給出了他們的答案:fluttet_boost

我們知道 Flutter 整個專案都是繪製在一個 Surface 畫布上,而fluttet_boost 將堆疊統一到了原生層,通過一個單例的 flutter engine 進行繪製。

每個 FlutterFragmentFlutterActivity 都是一個 Surface承載容器,切換頁面時就是切換 Surface 渲染顯示,而對於不渲染的頁面通過 Surface 截圖快取畫面顯示。

Flutter完整開發實戰詳解(十四、混合開發打包 Android 篇)

這樣整個 Flutter 的路由就被對映到原生堆疊中,統一由原生頁面堆疊管理,Flutter 內每 push 一個頁面就是開啟一個 Activity

flutter_boost 截止到我測試的時間 2019-05-16, 只支援 1.2之前的版本。 flutter_boost 的整體流程相對複雜,同時對於 Dialog 的支援並不好,且業務跳轉深度太深時會出現黑屏問題。

Flutter完整開發實戰詳解(十四、混合開發打包 Android 篇)

自此,第十四篇終於結束了!(///▽///)

資源推薦

完整開源專案推薦:
文章

《Flutter完整開發實戰詳解(一、Dart語言和Flutter基礎)》

《Flutter完整開發實戰詳解(二、 快速開發實戰篇)》

《Flutter完整開發實戰詳解(三、 打包與填坑篇)》

《Flutter完整開發實戰詳解(四、Redux、主題、國際化)》

《Flutter完整開發實戰詳解(五、 深入探索)》

《Flutter完整開發實戰詳解(六、 深入Widget原理)》

《Flutter完整開發實戰詳解(七、 深入佈局原理)》

《Flutter完整開發實戰詳解(八、 實用技巧與填坑)》

《Flutter完整開發實戰詳解(九、 深入繪製原理)》

《Flutter完整開發實戰詳解(十、 深入圖片載入流程)》

《Flutter完整開發實戰詳解(十一、全面深入理解Stream)》

《Flutter完整開發實戰詳解(十二、全面深入理解狀態管理設計)》

《Flutter完整開發實戰詳解(十三、全面深入觸控和滑動原理)》

《跨平臺專案開源專案推薦》

《移動端跨平臺開發的深度解析》

我們還會再見嗎?

相關文章