本文目標(biāo)
- 將 Flutter 引入到日常的開(kāi)發(fā);
- 熟悉引入 Flutter 開(kāi)發(fā)后由開(kāi)發(fā)到交付產(chǎn)品的流程;
一個(gè)簡(jiǎn)單的流程圖,來(lái)表示一下引入 Flutter 后的開(kāi)發(fā)流程:

三個(gè) channel
通常情況下,在現(xiàn)有工程中接入 Flutter 是大部分開(kāi)發(fā)者的選擇,即混編。這既兼顧到了大部分開(kāi)發(fā)者以 Native 開(kāi)發(fā)的現(xiàn)狀,又能嘗一下螃蟹的味道。基于此,我們來(lái)看一下一個(gè)比較重要的概念 channel。
在混編過(guò)程中避免不了原生與 Flutter 側(cè)的數(shù)據(jù)傳遞和方法相互調(diào)用,F(xiàn)lutter 提供了三個(gè) channel 專門去解決這個(gè)比較重要的問(wèn)題。
這三個(gè) channel 分別是 MessageChannel,MethodChannel,EventChannel,下面分別看一下。
以 Flutter 與 iOS 混編為例,以源碼形式集成 Flutter Module ,執(zhí)行 pod install 之后會(huì)自動(dòng)生成以下三個(gè) channel 類。
FlutterBasicMessageChannel
作用:用于 Native 與 Flutter 傳遞數(shù)據(jù)。下面是該類提供的三個(gè)比較重要的方法。
// Native 向 Flutter 側(cè)傳遞數(shù)據(jù)
- (void)sendMessage:(id _Nullable)message;
// Native 向 Flutter 側(cè)傳遞數(shù)據(jù),并接收 Flutter 側(cè)的回調(diào)
- (void)sendMessage:(id _Nullable)message reply:(FlutterReply _Nullable)callback;
// 注冊(cè)一個(gè)回調(diào),用于接收 Flutter 側(cè)返回的回調(diào)
- (void)setMessageHandler:(FlutterMessageHandler _Nullable)handler;
FlutterMethodChannel
作用:用于 Native 與 Flutter 之間方法的相互調(diào)用。下頁(yè)是該類提供的三個(gè)比較重要的方法。
// Native 調(diào)用 Flutter 側(cè)的方法,并傳參
- (void)invokeMethod:(NSString*)method arguments:(id _Nullable)arguments;
// Native 調(diào)用 Flutter 側(cè)的方法,并傳參,接收 Flutter 側(cè)返回的回調(diào)
- (void)invokeMethod:(NSString*)method
arguments:(id _Nullable)arguments
result:(FlutterResult _Nullable)callback;
// 監(jiān)聽(tīng) Flutter 側(cè)的方法回調(diào)并做相應(yīng)處理
- (void)setMethodCallHandler:(FlutterMethodCallHandler _Nullable)handler;
FlutterEventChannel
作用:Native 向 Flutter 側(cè)發(fā)送通知。下面是該類發(fā)送通知的核心方法。
// Native 向 Flutter 側(cè)發(fā)送通知,F(xiàn)lutter 側(cè)接收到通知后可以執(zhí)行相應(yīng)的操作
- (void)setStreamHandler:(NSObject<FlutterStreamHandler>* _Nullable)handler;
Flutter 與 Android 混編,以源碼形式集成 Flutter Module 時(shí),在 build 之后也會(huì)生成對(duì)應(yīng)的三個(gè) channel,含義和用法與上面是一樣的,就不再列出介紹了。
看完上面三個(gè) channel,是不是感覺(jué)這個(gè)交互方式有點(diǎn)熟悉。是不是跟 Native 接入 Hybrid 后兩者之間的交互方式是類似的的,區(qū)別在于 Native 無(wú)法向 Hybrid 直接發(fā)送通知。你細(xì)品!
三種開(kāi)發(fā)模式
三種開(kāi)發(fā)模式是本篇的重點(diǎn),但這里也不做具體詳細(xì)的介紹,只介紹其中的關(guān)鍵銜接之處。
Android 與 Flutter 混編
將 Flutter 集成到現(xiàn)有 Android 工程可能參考官方文檔,這里主要介紹一下 Android 與 Flutter 銜接的點(diǎn)。
在以 Flutter Module 源碼集成后,會(huì)生成一個(gè) FlutterView 的類,用于 Android 調(diào)起 Flutter 側(cè)的視圖。實(shí)例化 FlutterView 的一個(gè)對(duì)象并添加到 Android 端的殼 activity 中,即可以實(shí)現(xiàn) Android 加載 Flutter 側(cè)視圖的功能。關(guān)鍵代碼如下
FlutterView flutterView = new FlutterView(this);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
FrameLayout flContainer = findViewById(R.id.layout001);
flContainer.addView(flutterView, lp);
Native 與 Flutter 之間的數(shù)據(jù)傳遞,方法調(diào)用,通知?jiǎng)t以方法相互調(diào)用為例說(shuō)明。
MethodChannel nativeChannel = new MethodChannel(flutterEngine.getDartExecutor(), 'channel_native');
nativeChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
switch (call.method){
case "openSecondNative":
// 這里執(zhí)行具體的操作...
result.success("成功打開(kāi)第二個(gè)原生頁(yè)面");
break;
case "backFirstNative":
// 這里執(zhí)行具體的操作...
result.success("成功返回第一個(gè)原生頁(yè)面");
break;
case "backAction":
// 這里執(zhí)行具體的操作...
result.success("成功通過(guò)虛擬按鍵返回第一個(gè)原生頁(yè)面");
break;
default :
result.notImplemented();
break;
}
}
});
iOS 與 Flutter 混編
將 Flutter 集成到現(xiàn)有 iOS 工程可能參考官方文檔,這里也主要介紹一下 Android 與 Flutter 銜接的點(diǎn)。
在以 Flutter Module 源碼集成后,會(huì)生成一個(gè) FlutterViewController 的類,用于 iOS 調(diào)起 Flutter 側(cè)的視圖。實(shí)例化 FlutterViewController 的一個(gè)對(duì)象并 push 或 present 該對(duì)象,即可以實(shí)現(xiàn) iOS 加載 Flutter 側(cè)視圖的功能。關(guān)鍵代碼如下
let flutterVC = FlutterViewController()
flutterVC.fd_prefersNavigationBarHidden = true
flutterVC.setInitialRoute(paramsJsonStr)
let messageChannel = FlutterMethodChannel(name: "channel_native", binaryMessenger: flutterVC.binaryMessenger)
messageChannel.setMethodCallHandler { [weak self] call, result in
if call.method == "backToMineViewController" {
self?.navigationController?.popViewController(animated: true)
if let tmpArguments = call.arguments as? [AnyHashable: Any] {
let message = tmpArguments["message"] as? String
LoadingManager.showText(message)
}
} else if call.method == "didSelectCell" {
if let tmpArguments = call.arguments as? [AnyHashable: Any] {
self?.handleJump(with: tmpArguments)
}
}
}
flutterVC.hidesBottomBarWhenPushed = true
navigationController?.pushViewController(flutterMessageCenterVC, animated: true)
Native 與 Flutter 之間的數(shù)據(jù)傳遞,方法調(diào)用,通知也以他們之間的方法相互調(diào)用為例說(shuō)明??瓷戏酱a。
純 Flutter 開(kāi)發(fā)
對(duì)于一個(gè)全新的 App 來(lái)說(shuō),選擇純 Flutter 方式開(kāi)發(fā)或許是一個(gè)不錯(cuò)的選擇。
一是不用去踩混編的坑,二是越純粹越簡(jiǎn)單,包袱也少;
開(kāi)發(fā)完成之后,分別構(gòu)建各端上的包即可。
一處開(kāi)發(fā),到處運(yùn)行,簡(jiǎn)直不能太愛(ài)了!
構(gòu)建 ipa 或 apk 包
構(gòu)建包首先要注意的是需要支持哪些架構(gòu)類型,這關(guān)系到你的包發(fā)行的廣度的問(wèn)題。下面分別看一下 android 和 iOS 支持的架構(gòu)類型。
Android 支持的架構(gòu)
| 架構(gòu)類型 | 簡(jiǎn)介 |
|---|---|
| arm64-v8a | 第8代,64位,包含AArch32、AArch64兩個(gè)執(zhí)行狀態(tài)對(duì)應(yīng)32、64bit |
| armeabi | 第5代 ARM v5TE,使用軟件浮點(diǎn)運(yùn)算,兼容所有ARM設(shè)備,通用性強(qiáng),速度慢 |
| armeabi-v7a | 第7代 ARM v7,使用硬件浮點(diǎn)運(yùn)算,具有高級(jí)擴(kuò)展功能(從2010年起) |
| x86 | intel 32位,一般用于平板(從2011年起) |
| x86_64 | intel 64位,一般用于平板(從2014年起) |
| mips | 比較少見(jiàn)(目前市面幾乎沒(méi)有采用這種架構(gòu)的手機(jī)) |
| mips64 | 比較少見(jiàn)(目前市面幾乎沒(méi)有采用這種架構(gòu)的手機(jī)) |
設(shè)置支持特定架構(gòu)的包,可以在主工程 app 文件夾下的 build.gradle 添加下面的代碼
defaultConfig {
ndk {
abiFilters "armeabi-v7a", "x86", "armeabi"
}
}
iOS 支持的架構(gòu)
| 架構(gòu)類型 | 簡(jiǎn)介 |
|---|---|
| armv7s | iPhone5、iPhone5C、iPad4(iPad with Retina Display) |
| armv7 | iPhone4、iPhone4S、iPad、iPad2、iPad3(The New iPad)、iPad mini、iPod Touch |
| armv6 | iPhone, iPhone2, iPhone3G, 第一代、第二代 iPod Touch(一般不需要去支持) |
| arm64e | iphone XS、iphone XS Max、iphoneXR、iphone11、iphone11 Pro |
| arm64 | iPhone 5S、iPhone 6、iPhone 6 Plus、iPhone 6S、6S Plus、iPhone 7、7 Plus、iPad (2018)、iPhone 8、iPhone 8 Plus、and iPhone X |
| x86_64 | Mac指令集:x86_64是針對(duì)x86架構(gòu)的64位處理器 |
| i386 | Mac指令集:i386是針對(duì)intel通用微處理器32位處理器 |
可以在 Xcode 中如下圖所示的位置設(shè)置支持的架構(gòu)類型

安裝
Android apk 包安裝
adb install xxx.apk
iOS ipa 包安裝
Enterprise 企業(yè)包,tf 包
最后
也許一開(kāi)始引入 Flutter 會(huì)面臨各種各樣的問(wèn)題。
比如學(xué)習(xí)成本,新技術(shù)的不完備性等風(fēng)險(xiǎn),但后期帶來(lái)的收益也是很可觀的。
業(yè)務(wù)是在不斷變化的,對(duì)高效率的追求卻是不變的!Flutter 也許會(huì)是一個(gè)相對(duì)不錯(cuò)的選擇!
推薦學(xué)習(xí)實(shí)踐:
Flutter、Android混合開(kāi)發(fā)實(shí)踐:
https://juejin.cn/post/6844904065881604109
Flutter、iOS混合開(kāi)發(fā)實(shí)踐:
https://juejin.cn/post/6844904087918477320