Flutter混編之路——開發集成(iOS篇)

混編的模式下,需要兼顧現有工程的開發、集成、架構等問題,例如,我們的代碼里有Swift、有OC、有必須Bitcode的三方framework,這些會影響最終的集成方案。多人協作的項目中,還需要考慮開發人員對Flutter(任何其他語言也一樣)的學習成本和遷移過程。

零、SDK版本選擇

Flutter官方文檔中提供了下載Flutter SDK的地址。但考慮到Flutter的升級頻率相比某些跨平臺方案來說要高一些,而且整體質量和團隊投入度比較高,從而保證了可用性,因此,如果你希望以后方便升級Flutter SDK,那還是建議使用clone Github源碼的方式。注意:官方建議使用Beta分支來做開發環境(master是日常開發環境,不保證穩定性)。一般而言,Beta環境最新代碼默認會帶某個版本號的Tag,如果沒有,切換到最新的一個Tag上。

一、開發方式

相信大部分團隊在做Flutter混編的項目時,一定是少部分人做Flutter開發,同時另一部分同學還是只做Native開發的,隨著大家對Flutter的熟悉程度加深,再一步步轉過來。在這過程中,Native開發同學需要對Flutter的開發環境、SDK及版本、Dart代碼等無感,這就要求我們必須有“源碼”和“產物”兩套開發方式。

二、集成方案

工具選擇方面,大部分基于Objective-C開發的iOS應用,都是用CocoaPods做組件管理工具的。如果是純Swift,還可能是Cathage。

我們的項目是OC與Swift混編的,由于App體積并不大,當初選擇用CocoaPods把依賴庫以Framework形式集成,對App的啟動速度影響并不明顯。在Flutter混編中,選擇基于CocoaPods(1.5.0+)的組件集成方案。

基于不同開發方式,我們需要提供快速切換的方式,對開發者來說,最好是不需要操作,簡單的一步操作次之。由于是以組件形式依賴的,我們可以通過修改Podfile的變量,快速切換Pod命令,然后執行Pod install:

Flutter source code的兩行代碼是要讀取并執行flutter工程(非SDK)的文件夾中的腳本,它是flutter自動生成的,我們做了一點修改。其主要是根據環境選擇相應的SDK物料,將其放到Podfile中集成。后面我們會分析這個文件中的代碼。

三、源碼集成

在上述“集成方案”中的圖片中可以看到,源碼集成中用到了podhelp.rb。

這個ruby腳本中其實代碼就這20行,主要就是把SDK文件夾中的Flutter.framework和Plugin相關的Pod集成進來。

四、Flutter產物集成

編譯時用到了xcode_backend.sh,我們剖析下:


上圖就是 Release.podspec 中做的唯一的事情——把他們打成一個包,集成進主工程。


這個圖就是集成后的FlutterModule(前面說過,我們的工程中使用的是".framework",你的可以是".a"),其中:

App是我們自己寫的Dart代碼(名字就是App,別懷疑? :));

Flutter是SDK的產物;

FlutterPluginRegistrant是注冊模塊,如果你的Flutter項目中引用了Plugin,就會有這個產物。

hybrid_stack_manager是阿里閑魚團隊開發的 頁面堆棧管理 模塊,(在這里做個廣告,康哥在我們開發過程中給了不少建議和幫助)。

tbridge是我們自己寫的一個Plugin

Resources里面的flutter_assets是一個資源文件容器,Debug模式下如圖。(Release模式下只有前三個和LICENSE,其他的幾個都被打入了App中)

文件作用解釋:(引用自http://www.lxweimin.com/p/f44db0d088e5)

isolate_snapshot_data:用于加速 isolate 啟動,業務無關代碼,固定,僅和 flutter engine?版本有關;

vm_snapshot_data: 用于加速 Dart VM 啟動的產物,業務無關代碼,僅和 flutter engine 版本有關;

platform.dill:和 Dart VM 相關的 kernel 代碼,僅和 Dart 版本以及 engine?編譯版本有關。固定,業務無關代碼;

kernel_blob.bin:業務代碼產物


那么,這些產物怎么生成的呢?

答案是,從flutter工程中編譯Run工程,或者用Flutter build命令生成,然后手動copy到主工程的。

首先,如果在yaml中加了plugin,就需要在命令行中執行flutter package get,flutter會在ios文件夾中自動生成podfile文件,執行了pod install后,打開Run.xcworkspace 在Run工程的Build Phases中,Run Script中已經加入了

/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build?這行命令,每次編譯之前都會運行這個shell腳本,我們來看看它都做了些什么。

1. 根據編譯環境(FLUTTER_BUILD_MODE)選擇相應的SDK framework(在踩坑記錄里有提到),拷貝到Flutter文件夾里


2. 根據debug/release來選擇 執行flutter build aot 命令還是運行clang


3. 再次,執行 flutter build bundle,生成相應的文件。


4. 這時候,我們在本地的DerivedData文件中就可以找到相應的產物了,例如 yaml中的plugin等。


此時,再次編譯整個Run工程,就可以以上述產物為依賴進行整個工程的編譯鏈接了。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容