本文首發於微信公衆號「Android開發之旅」,歡迎關注 ,獲取更多技術乾貨
前一篇文章講解了Android原生工程如何集成Flutter項目的具體過程,Flutter混合開發(一):Android項目集成Flutter模塊詳細指南 ,本篇將帶着你們來一塊兒學習原生iOS項目如何集成Flutter。html
由於每一個版本的集成邏輯都是有差異的,因此這裏交代下本篇文章的集成版本:android
Flutter (channel dev,v1.10.16)
dart (v2.7.0)
Xcode (v11.2)
cocoapds (1.8.4)
假如iOS項目的路徑是這樣的:flutter/flutter_hybrid/iOS Project,那麼咱們須要在iOS Project上一層目錄flutter_hybrid中建立Flutter module。ios
cd flutter/flutter_hybrid/ flutter create -t module flutter_module
輸入後控制檯打印以下:git
$ flutter create -t module flutter_module Creating project flutter_module... flutter_module/test/widget_test.dart (created) flutter_module/flutter_module.iml (created) flutter_module/.gitignore (created) flutter_module/.metadata (created) flutter_module/pubspec.yaml (created) flutter_module/README.md (created) flutter_module/lib/main.dart (created) flutter_module/flutter_module_android.iml (created) flutter_module/.idea/libraries/Flutter_for_Android.xml (created) flutter_module/.idea/libraries/Dart_SDK.xml (created) flutter_module/.idea/modules.xml (created) flutter_module/.idea/workspace.xml (created) Running "flutter pub get" in flutter_module... 1.2s Wrote 12 files. All done! Your module code is in flutter_module/lib/main.dart.
看到All done就表示咱們項目建立好了。整個module目錄和原生Flutter基本同樣,主要就是Android、iOS的宿主工程和lib目錄以及pubspec.yaml文件。json
爲iOS項目添加依賴須要使用CocoaPods,若是你尚未用到CocoaPods,能夠參考https://cocoapods.org/上面的說明來安裝CocoaPods。segmentfault
若是你的項目以前沒有使用過cocoapods,那麼須要進行初始化生成podfile文件,進入iOS項目的根目錄執行:數組
pod init
而後打開podfile文件,進行配置:微信
# 配置 flutter_application_path = '../flutter_module/' load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb') target 'iOSFlutterHybrid' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! # Pods for iOSFlutterHybrid # 配置 install_all_flutter_pods(flutter_application_path) target 'iOSFlutterHybridTests' do inherit! :search_paths # Pods for testing end target 'iOSFlutterHybridUITests' do # Pods for testing end
配置添加好後在項目根目錄運行如下命令進行安裝:session
pod install
控制檯輸出:app
Analyzing dependencies Downloading dependencies Installing Flutter (1.0.0) Installing FlutterPluginRegistrant (0.0.1) Installing flutter_module (0.0.1) Generating Pods project Integrating client project [!] Please close any current Xcode sessions and use `iOSFlutterHybrid.xcworkspace` for this project from now on. Pod installation complete! There are 3 dependencies from the Podfile and 3 total pods installed. [!] Automatically assigning platform `iOS` with version `13.2` on target `iOSFlutterHybrid` because no platform was specified. Please specify a platform for this target in your Podfile. See `https://guides.cocoapods.org/syntax/podfile.html#platform`.
這裏咱們看到有三個依賴安裝完成了。並提醒咱們關閉當前項目,在根目錄下面使用iOSFlutterHybrid.xcworkspace來打開運行項目。這裏可能不少人在執行命令的時候會發現提示0個依賴完成。這裏有多是你的Xcode版本的問題。由於Flutter要求最低版本是10.2及以上。
當在flutter_module/pubspec.yaml中添加一個Flutter插件時,須要在flutter_module目錄下運行:
flutter packages get
來刷新podhelper.rb腳本中的插件列表,而後在iOS目錄下運行:
pod install
這樣podhelper.rb腳本才能確保添加的插件和Flutter.framework可以添加到iOS項目中。
目前Flutter還不支持Bitcode,因此集成了Flutter的iOS項目須要禁用Bitcode。
在如下路徑下找到Bitcode並禁用:
Build Settings->Build Options->Enable Bitcode
flutter之前的版本是須要添加build phase以構建Dart代碼,可是最新的版本已經不須要添加了,能夠自動構建。
Flutter爲咱們提供了兩種調用方式:FlutterViewController和FlutterEngine,FlutterEngine在使用的時候會有一些問題,將在下文進行說明。
咱們打開ViewController.m文件,在裏面添加一個加載flutter頁面的方法而且添加一個按鈕看來調用:
#import "ViewController.h" #import <Flutter/Flutter.h> #import "AppDelegate.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; [button addTarget:self action:@selector(handleButtonAction) forControlEvents:UIControlEventTouchUpInside]; [button setTitle:@"加載Flutter" forState:UIControlStateNormal]; [button setBackgroundColor:[UIColor blueColor]]; button.frame = CGRectMake(100, 100, 160, 60); [self.view addSubview:button]; } - (void)handleButtonAction{ FlutterViewController *flutterViewController =[FlutterViewController new]; //設置路由參數 [flutterViewController setInitialRoute:@"route2"]; [self presentViewController:flutterViewController animated:false completion:nil]; } @end
當咱們運行項目點擊加載Flutetr按鈕時,將會調用Flutter頁面。和Android項目集成同樣,這裏的setInitialRoute能夠設置一個json數組來傳遞須要交互的參數。並在Flutter中使用window.defaultRouteName來獲取傳遞的參數。
咱們須要在AppDelegate中對FlutterEngine進行初始化。打開AppDelegate.h文件:
#import <UIKit/UIKit.h> #import <Flutter/Flutter.h> @interface AppDelegate : FlutterAppDelegate @property (nonatomic,strong) FlutterEngine *flutterEngine; @end
在打開AppDelegate.m文件:
// 若是你須要用到Flutter插件時 #import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h> #include "AppDelegate.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.flutterEngine = [[FlutterEngine alloc] initWithName:@"io.flutter" project:nil]; [self.flutterEngine runWithEntrypoint:nil]; [GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine]; //若是你須要用到Flutter插件時 return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @end
而後在ViewController.m文件定義的handleButtonAction中調用:
- (void)handleButtonAction{ FlutterEngine *flutterEngine = [(AppDelegate *)[[UIApplication sharedApplication] delegate] flutterEngine]; FlutterViewController *flutterViewController = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil]; [flutterViewController setInitialRoute:@"route2"]; [self presentViewController:flutterViewController animated:false completion:nil]; }
當咱們運行項目點擊加載Flutter按鈕時,將會調用Flutter頁面。前文講到使用FlutterEngine會有問題,就是咱們setInitialRoute傳遞的參數在flutter中永遠獲取到的都是 「/」 ,這個是Fltter SDK的一個Bug,因此若是必須依賴setInitialRoute,仍是使用FlutterViewController的形式來加載Flutter模塊。
你們在寫純Flutter應用的時候,知道是有熱重啓/從新加載功能的,可是在作混合開發的過程當中,你會發現熱重啓/從新加載功能失效了。那麼如何在混合開發中開啓熱重啓/從新加載功能呢?
$ flutter attach Waiting for a connection from Flutter on Android SDK built for x86...
複製代碼此時就在等待設備的鏈接。這裏要注意的是,若是電腦鏈接了多臺設備須要使用 -d 命令來指定一臺設備,參數爲設備的id。
flutter attach -d '你的設備id'
而後啓動咱們的應用會看到控制檯輸出:
Done. Syncing files to device Android SDK built for x86... 1,393ms 🔥 To hot reload changes while running, press "r". To hot restart (and rebuild state), press "R". An Observatory debugger and profiler on Android SDK built for x86 is available at: http://127.0.0.1:59354/zRsDBfpesrk=/ For a more detailed help message, press "h". To detach, press "d"; to quit, press "q".
這樣就表示咱們鏈接成功了。在輸出的日誌中也告訴了咱們如何使用熱重啓/從新加載功能。
在Terminal中輸入如下命令:
r : 熱加載; R : 熱重啓; h : 獲取幫助; d : 斷開鏈接; q : 退出;
這裏的的 d 和 q 的命令都有退出調試,區別在於 d 命令只是單純的斷開而 q 命令會將應用退到後臺。
一樣在混合開發過程當中咱們如何調試dart代碼呢?
接下來就能夠像調試普通Flutter項目同樣來調試混合開發模式下的Dart代碼了。
本文主要是講解了iOS集成Flutter項目的步驟,其中也遇到了一些問題,因爲個人Xcode版本較低,在集成的過程當中iOS項目的依賴一直失敗。最後才發現是Xcode的版本問題。這裏花費了不少時間去排查問題,因此你們在集成的過程當中有問題能夠關注公衆號加我微信,給我留言,我會幫助你們解決問題。
所有Demo源碼已經上傳到後臺,關注公衆號回覆「混合開發」便可得到下載連接。
若是你以爲文章還不錯,請你們點贊分享下,你的確定是對我最大的鼓勵和支持。
Flutter混合開發(一):Android項目集成Flutter模塊詳細指南
Flutter混合開發(三):Android與Flutter之間通訊詳細指南