Flutter 混合開發 (互動通訊)
互動通訊
Flutter 與原生之間的通訊依賴靈活的訊息傳遞方式:
1,Flutter 部分通過平臺通道將訊息傳送到其應用程式的所在的宿主環境(原生應用)。
2,宿主環境通過監聽平臺通道,接收訊息。然後它會呼叫平臺的 API,響應 Flutter 傳送的訊息。
Flutter主動 呼叫 宿主環境
在 Flutter 中通過 MethodChannel 的 API 可以傳送與方法相對於的訊息,宿主環境 iOS 中通過 FlutterMethodChannel 接受方法的呼叫並返回結果。
Flutter 需要引入services.dart模組才可以使用 MethodChannel
import'package:flutter/services.dart';
Flutter 中的呼叫程式碼
constmethodChannel =constMethodChannel("com.pages.flutter/call_native");
RaisedButton(
child: Text("call_native_method_no_params"),
onPressed: (){
methodChannel.invokeMethod("call_native_method_no_params",null);
},
),
RaisedButton(
child: Text("call_native_method_params"),
onPressed: (){
Map<String,String> params = {"params":"flutter params"};
methodChannel.invokeMethod("call_native_method_params",params);
},
),
RaisedButton(
child: Text("call_native_method_native_result_callback"),
onPressed: (){
_nativeCallbackWithParams();
},
),
Text(_content,style: TextStyle(color: Colors.red),)
Future<Null> _nativeCallbackWithParams() async{
dynamic result;
try {
result = await methodChannel.invokeMethod(
"call_native_method_native_result_callback", null);
} on PlatformException catch (e) {
result = "Failed to get params: '${e.message}'.";
}
setState(() {
_content = result;
});
}
iOS 中的呼叫程式碼
FlutterViewController* flutterViewController = [[FlutterViewController alloc] init];
flutterViewController.fd_prefersNavigationBarHidden = YES;
FlutterMethodChannel * messageChannel = [FlutterMethodChannel methodChannelWithName:@"com.pages.flutter/call_native" binaryMessenger:flutterViewController];
[messageChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
NSLog(@"flutter call native:\n method=%@ \n arguments = %@",call.method,call.arguments);
if ([call.method isEqualToString:@"call_native_method_native_result_callback"]) {
if (result) {
result(@"flutter hello");
}
}else if([call.method isEqualToString:@"call_native_method_pop_flutter_nav"]){
[weakSelf.navigationController popViewControllerAnimated:YES];
}
}];
[self.navigationController pushViewController:flutterViewController animated:YES];
分別看下控制檯輸出:
flutter call native:
method=call_native_method_no_params
arguments = (null)
flutter call native:
method=call_native_method_params
arguments = {
params = "flutter params";
}
第三個事件會在 Flutter 頁面顯示flutter hello 該值由宿主環境返回。
注意:這裡有個設計上的細節,上節提到過就是導航欄的問題,因為宿主環境有個導航欄,而 Flutter 自身也有導航欄,出現了矛盾,到底我們應該保留宿主環境的,還是 Flutter 頁面使用自身,隱藏宿主環境的導航欄。我個人覺得後則更合理,Flutter 頁面更瞭解自己導航欄具體功能、主題、互動及顯示,我們只需要處理點選返回按鈕 pop 回到宿主環境中,如下:
appBar: AppBar(
title: Text('Flutter Page') ,
leading: IconButton(icon: Icon(Icons.arrow_back_ios), onPressed:()=>methodChannel.invokeMethod("call_native_method_pop_flutter_nav",null)),
),
我們只需要在宿主環境中監聽到該事件後呼叫導航的 pop 功能。
資源搜尋網站大全 https://www.renrenfan.com.cn 廣州VI設計公司https://www.houdianzi.com
宿主環境主動呼叫 Flutter
一般可以用作宿主環境為 Flutter 提供引數
EventChannel 是 Flutter 監聽宿主環境的 API ,FlutterEventChannel 是 iOS 宿主環境與 Flutter 互動平臺通道的 API 。
Flutter 程式碼片段
constEventChannel eventChannel =constEventChannel('com.pages.flutter/call_flutter');
@override
void initState(){
super.initState();
eventChannel.receiveBroadcastStream(12345).listen(_onEvent,onError: _onError);
}
void _onEvent(Object event){
setState(() {
_content = event.toString();
});
}
void _onError(Object error){
setState(() {
_content = error.toString();
});
}
iOS 宿主環境程式碼片段
NSString *eventChannelName = @"com.pages.flutter/call_flutter";
FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:eventChannelName binaryMessenger:flutterViewController];
[eventChannel setStreamHandler:self];
- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events {
if (events) {
events(@"hi flutter");
}
return nil;
}
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {
return nil;
}
兩端互動通訊方式就是這樣的,這裡也只是介紹了他們通訊的方式,具體如何優雅的封裝、規範互動流程還需要我們自己去考慮下。