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

本篇將帶你深刻了解 Flutter 中打包和插件安裝等原理,幫你快速完成 Flutter 集成到現有 Android 項目,實現混合開發支持。java

前文:react

1、前言

隨着各類跨平臺框架的不斷涌現,不少時候咱們會選擇混合開發模式做爲腳手架 ,由於企業通常不會把業務都壓在一個框架上,同時除非是全新項目,否則出於對原有業務重構的 成本和風險 考慮,都會選擇混合開發去嘗試入坑。android

可是混合開發會對 打包、構建和啓動等流程熟悉度要求較高 ,同時遇到的問題也更多,之前我在 React Native 也寫過相似的文章 :《從Android到React Native開發(4、打包流程解析和發佈爲Maven庫)》 ,而這方面是有不少經驗能夠通用的,因此適當的混開模式有利於避免一些問題,同時只有瞭解 Flutter 總體項目的構建思路,纔有可能更溫馨的躺坑。git

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

官方將來將有 Flutter build aar 的方法可提供使用。

2、打包

通常跨平臺混合開發會有兩種選擇:web

  • 一、將 Flutter 總體框架依賴和打包腳本都集成到主項目中。
  • 二、以 aar 的完整庫集成形式添加到主項目。

兩種實現方法各有利弊:npm

  • 第一種方式能夠更方便運行時修改問題,可是對主項目「污染」會比較高,同時改動會大一些。react-native

  • 第二種方式 須要單獨調試後,更新 aar 文件再集成到項目中調試,可是這類集成方式更乾淨,同時 Flutter 相關代碼可獨立運行測試,且改動較小。緩存

通常而言,對於普通項目我是建議以 第二種方式集成到項目中的 ,經過新建一個 Flutter 工程,而後對工程進行組件化腳本處理,讓它 既能以 apk形式單獨運行調試,又能打包爲aar形式對外提供支持。app

相信對於原平生臺熟悉的應該知道,咱們能夠經過簡單修改項目gradle 腳本,讓它快速支持這個能力,以下圖片所示,圖片中爲省略的部分腳本代碼,完整版可見 flutter_app_lib

咱們經過了 isLib 標記爲去簡單實現了項目的打包判斷,當項目做爲 lib 發佈時,設置 isLib 爲 true,以後執行 ./gradlew assembleRelease 便可 ,剩下的工做依舊是 Flutter 自身的打包流程,而對於打包後的 aar 文件直接在原生項目裏引入便可完成依賴。

而通常接入時,若是須要 token 、用戶數據等信息,推薦提供定義好原生接口,如 init(String token, String userInfo) 等,而後經過MethodChannel 將信息同步到 Flutter 中。

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

你可能須要修改的還有 AndroidManifset 中的啓動 MainActivity 移除,而後添加一個自定義 Activity 去繼承 FlutterActivity 完成自定義。

3、插件

若是普通狀況下,到上面就能夠完成 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 文件中。

而在 android 工程的 settings.gradle 裏,以下圖所示,會經過讀取該文件將 .flutter-plugins 文件中的項目一個個 include 到主工程裏。

以後就是主工程裏的 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 腳本的引入了,這個腳本通常在於 flutterSDK/packages/flutter_tools/gradle/ 目錄下,以下代碼所示,其中最關鍵的部分一樣是 讀取 .flutter-plugins 文件中的項目,而後一個一個再 implementation 到主工程裏完成依賴。

自此全部原生代碼的 Flutter 插件,都被做爲本地 Module Project 的形式引入主工程了 ,最後腳本會自動生成一個 GeneratedPluginRegistrant.java 文件,實現原生代碼的引用註冊, 而這個過程對你徹底是無感的。

說了那麼多就是爲了說明,既然插件是被看成本地 Module Project 的形式引入,那麼這時候按照原來直接打包 aar 是會有問題的:

`Android` 默認 `gradle` 腳本打包時,對於 `project` 和遠程依賴只會打包引用而不會打包源碼和資源。

因此這時候就須要 fat-aar 的加持了,關於 fat-aar 的詳細概念可見 :《從Android到React Native開發(4、打包流程解析和發佈爲Maven庫)》 ,這裏能夠簡單理解爲,這是一個支持將引用代碼和資源到合併到一個 aar 的插件。

以下代碼所示,咱們在本來的組件化腳本上,經過增長 apply plugin: 'com.kezong.fat-aar' 引入插件,而後參考 Flutter 腳本對 .flutter-plugins 文件中的項目進行 embed 依賴引用便可 ,這時候再打包出的 aar 文件即爲完整 Flutter 項目代碼。

完整版可見 flutter_app_lib

4、堆棧

最後須要說的問題就是堆棧了。

若是說混合開發中最難處理的是什麼,那必定是各平臺之間的堆棧管理,通常狀況下咱們都會避免混合堆棧的相互調用 ,可是面對不得不如此爲之的狀況下,閒魚給出了他們的答案:fluttet_boost

咱們知道 Flutter 整個項目都是繪製在一個 Surface 畫布上,而fluttet_boost 將堆棧統一到了原生層,經過一個單例的 flutter engine 進行繪製。

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

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

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

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

資源推薦

完整開源項目推薦:

咱們還會再見嗎?
相關文章
相關標籤/搜索