首先區分兩個概念'flutter-boot' 和'flutter_boost'都是alibba開源的flutter工具,可是是兩個徹底不一樣的東西。node
新一代Flutter-Native混合解決方案。 FlutterBoost是一個Flutter插件,它能夠輕鬆地爲現有原生應用程序提供Flutter混合集成方案。FlutterBoost的理念是將Flutter像Webview那樣來使用。在現有應用程序中同時管理Native頁面和Flutter頁面並不是易事。 FlutterBoost幫你處理頁面的映射和跳轉,你只需關心頁面的名字和參數便可(一般能夠是URL)。android
這是一個幫助你在已有原生應用的狀況下,搭建flutter混合開發環境的工具。 咱們提供了標準的混合工程結構,同時支持混合棧(一套原生和flutter以前頁面通訊和過渡的方案)的快速接入。ios
以上是摘抄GitHub上flutter-boot 和 flutter_boost的官方介紹,也由於官方文檔上的集成步驟太過簡略,在集成的過程當中才過了很多的坑,因此都記錄下來而且分享出來,但願能夠給看文章的你,帶去一些解決方案和思路。git
本文主要記錄一次flutter-boot的集成過程,對於flutter_boost的使用放在後續的文章中再介紹。github
已有一個維護迭代過多個版本的Native工程,而且已經作過組件化,拆分了多個組件(就是常見的組合組件的方法,經過CocoaPods的方式添加安裝各個組件,製做CocoaPods遠程私有庫,將其發不到公司的gitlab或GitHub,使工程可以Pod下載下來),本次集成flutter-boot的目的是要把其中一個組件,使用flutter重寫。shell
這裏強調作過組件化,是由於不少問題都是由於組件化了才引發的若是隻是一個單純的工程集成的話,會簡單很多,並且後續若是隻是某個組件須要依賴flutter,還須要有一些特殊的操做。npm
這裏能夠跟着我一塊兒來操做,下面的步驟我都寫得儘可能詳細,遇到的問題都有截圖或者文字描述,以及解決方案跟在後面。ruby
這裏能夠是你的Native路徑 , 也能夠是一個新建立的文件夾,這裏我是用了一個新的文件夾路徑,目的是保證以後的路徑和官方文檔上的目錄結構一致。bash
somepath/my_repo
└──my_android
└──my_ios
└──my_flutter
└──.git
└──.gitignore
└──android_shell
└──ios_shell
└──android
└──ios
複製代碼
問題一:link 失敗,這裏忘記截圖了。。。特別抱歉app
解決方案:
擁有^1.5.0的flutter環境
複製代碼
問題二:podfile內容copy出錯,你也可能不會遇到這個問題,這裏是flutter-boot自己的bug,只去匹配了字符串'end',恰好咱們使用了這個日曆的庫,就到這裏把podfile文件中的內容給截斷了
pod 'FSCalendar', '2.8.0' # 日曆
複製代碼
解決方案:
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
target.build_configurations.each do |config|
...
end
end
end
複製代碼
問題三:
這裏是你工程的post_install和init命令生成的fbpodhelper.rb中的post_install衝突致使,
解決方案:
flutter_application_path = fbFlutterPath
require File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
複製代碼
改成:
# ============= Flutter config begin ============== #
flutter_application_path = './fpf_flutter/'
podhelper_path = File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
podhelper_content = File.read(podhelper_path);
podhelper_post_isntall = "post_install do |installer|";
# 當post_install重複時須要去重以免發生pod install錯誤:multiple post_install hooks is unsupported
if podhelper_content.scan(/(#{podhelper_post_isntall})/).length > 0 then
podhelper_buffer = podhelper_content.gsub(podhelper_post_isntall, "def update_configs(installer, framework_dir)")
eval(podhelper_buffer, binding)
else
eval(File.read(podhelper_path), binding)
end
# ============= Flutter config end ============== #
複製代碼
info [init] 你能夠在建立Android工程後調用 flutter-boot link來關聯flutter
info [init] 混合工程初始化完成
複製代碼
你覺得到這裏就真的完成了嗎,run一下~~ 記得要選擇 Runner target,好像確實能夠成功。可是flutter-boot的做用是你能夠有兩個開發視角,flutter視角下,不須要關心native,native視角,甚至能夠不用安裝flutter環境。那麼,去flutter視角看一下,把flutter module拖入VSCode打開,而後fn+f5,運行起來
那麼在flutter視角運行起來了嗎
問題四: Run Flutter Build Script 中的腳本./my_flutter_module/.ios/Flutter/flutter_export_environment.sh 路徑找不到,一個很奇怪的現象,pod install成功後查看路徑,沒問題,可是flutter run以後,這裏的路徑就改變了,相對路徑錯誤,確實找不到這個腳本
解決方案:
flutter_export_environment_path = File.join(project_directory_pathname, relative, 'flutter_export_environment.sh');
複製代碼
In AppDelegate.h:
@import UIKit;
@import Flutter;
@interface AppDelegate : FlutterAppDelegate
@property (nonatomic,strong) FlutterEngine *flutterEngine;
@end
複製代碼
In AppDelegate.m:
@import FlutterPluginRegistrant; // Only if you have Flutter Plugins
#import "AppDelegate.h"
@implementation AppDelegate
// This override can be omitted if you do not have any Flutter Plugins.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.flutterEngine = [[FlutterEngine alloc] initWithName:@"io.flutter" project:nil];
[self.flutterEngine runWithEntrypoint:nil];
[GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
複製代碼
In ViewController.m
#import "AppDelegate.h"
#import "ViewController.h"
@import Flutter;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:@selector(handleButtonAction)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"Press me" forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor blueColor]];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
}
- (void)handleButtonAction {
FlutterEngine *flutterEngine = [(AppDelegate *)[[UIApplication sharedApplication] delegate] flutterEngine];
FlutterViewController *flutterViewController = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
[self presentViewController:flutterViewController animated:false completion:nil];
}
@end
複製代碼
至此,flutter-boot 環境集成成功!!! 喜大普奔啊,終於不報錯了~~
可是,回到咱們最初集成flutter-boot的目的,是要使用flutter重寫某一個業務線。由於是組件化的工程,因此flutter引擎的註冊也不但願暴露在APPdelegate中,而是放在一個管理各個業務線分發的平臺組件中,那麼就涉及到,某一個組件中要使用flutter。
用唄,主工程都能用,組件同樣能用,而後,當你在組件代碼中添加以下代碼以後:
#import <Flutter/Flutter.h>
#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h>
複製代碼
找不着,各類找不着啊。。。好像各個業務線組件根本就不能引用flutter以及flutter_module
解決方案:到這裏集成flutter-boot 纔算取得了階段性的勝利✌️,但願這篇文章,能夠給廣大敢於嘗試flutter-boot的開發人員,帶去一些福利(主要是節省一些時間,都不是什麼難解決的問題,就是得不斷的嘗試)。
在這個過程當中,也去看了GitHub上他們全部開放和關閉的issues,而且嘗試了N次,過程比較坎坷,不過成功了仍是很可的事😃。
2019.12.11 補充 flutter-boot 推到遠端以後,其餘同事拉代碼,裝flutter-boot以後遇到的一些問題記錄:
問題一:
產生緣由: 曾用 root 用戶進行了局部安裝npm包,留下所屬權爲 root 的文件,致使普通用戶 沒法訪問 root的文件內容。
解決方案:
問題二:my_flutter_module中數據缺失
就是別的同事拉下flutter_module中的代碼裏面,沒有engine這個文件夾
解決方案:
問題三: native視角如何使用
其實這個也不能算是個問題啦,應該歸到上面的使用步驟裏面,畢竟這個flutter-boot的環境搭建起來,是要給你們一塊兒用的,又不是指給本身用😀
其實切換到native視角,就會以爲這個工具,和我最開始選擇用flutter-boot的初衷有一些偏離。最初,咱們是但願有一套徹底不影響原生開發的框架,去接入flutter,徹底不影響是什麼意思呢,領導但願,native開發,不須要安裝flutter環境,不須要,不須要,不須要,重要的地方強調一下,可是經過這幾天對flutter-boot的研究,發現根本作不到這一點。
首先別人拉下native代碼和flutter代碼以後,須要執行link命令去作軟鏈接,可是自己flutter-boot就是依賴flutter庫的,可能說依賴不太準確,可是link命令中就有判斷flutter版本的邏輯,若是沒有flutter的開發環境,這一步就過不去,那你的native和flutter如何連接上呢??
解決方案:
若是看這篇文章的小夥伴,有更好的方式,歡迎交流!!!