flutter 與原生通道封裝
channel_tools.dart文件
import 'package:flutter/services.dart'; import 'dart:async'; /* * 參考文檔 * 官網 https://flutter.cn/docs/development/platform-integration/platform-channels * Flutter與Native數據交互,MethodChannel https://www.jianshu.com/p/f2755c301a3e * Dart語法 http://dart.goodev.org/guides/language/language-tour * 雙向通訊:https://blog.csdn.net/zl18603543572/article/details/96043692 */ /* * 通道的客戶端和宿主端通過傳遞給通道構造函數的通道名稱進行連接 * 一個應用中所使用的所有通道名稱必須是唯一的 * 使用唯一的域前綴為通道名稱添加前綴,比如:samples.flutter.dev/battery */ /* * Flutter 與 Android iOS 原生的通信有以下三種方式 * BasicMessageChannel 實現 Flutter 與 原生(Android 、iOS)雙向通信 * MethodChannel 實現 Flutter 與 原生原生(Android 、iOS)雙向通信 * EventChannel 實現 原生原生(Android 、iOS)向Flutter 發送消息 僅支持數據單向傳遞,無返回值。 */ //構建通道 (唯一) xxxxxx 自定義通道標識 //BasicMessageChannel const basicMessageChannel = const BasicMessageChannel( 'xxxxxx', StandardMessageCodec()); //MethodChannel const methodChannel = const MethodChannel('xxxxxx'); //EventChannel const eventChannel = const EventChannel('xxxxxx'); /* * BasicMessageChannel * 實現Flutter 調用Android iOS原生方法並回調 * arguments 發送給原生的參數 ,自定義基本數據格式{"method": "test", "content": "flutter 中的數據", "code": 100} * return數據 原生發給Flutter的參數,自定義基本數據格式{"code":100,"message":"消息","content":內容} */ Future<Map> toolsBasicChannelMethodWithParams(Map arguments) async { var result; try { result = await basicMessageChannel.send(arguments); } catch (e) { result = {'Failed': e.message}; } return result; } /* * MethodChannel * 在方法通道上調用方法invokeMethod * methodName 方法名稱 * params 發送給原生的參數,自定義基本數據格式{"code":100,"message":"消息","content":內容} * return數據 原生發給Flutter的參數,自定義基本數據格式{"code":100,"message":"消息","content":內容} */ Future<Map> toolsMethodChannelMethodWithParams(String methodName, [Map params]) async { var res; try { res = await methodChannel.invokeMethod('$methodName', params); } catch (e) { res = {'Failed': e.message}; } return res; } /* * EventChannel * return數據 原生發給Flutter的參數,自定義基本數據格式{"code":100,"message":"消息","content":內容} * result listen監聽結果 */ toolsEventChannelMethod(Function result) { //不指定返回值類型,函數返回值默認為Object eventChannel.receiveBroadcastStream().listen(result); }
案例文件
import 'package:flutter/material.dart'; //導入ChannelTools文件 import 'package:flutter/services.dart'; import 'package:flutter_action/Channel/channel_tools.dart'; /* * 參考文檔 * https://flutter.cn/docs/development/platform-integration/platform-channels * https://www.jianshu.com/p/74c9e389e73f * https://blog.csdn.net/mcy456/article/details/96774539 * * */ class ChannelUseCasesRoute extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("MethodChannel使用案例"), actions: <Widget>[ ], ), body: ColumnWidget( ), ); } } class ColumnWidget extends StatefulWidget { @override _ColumnWidgetState createState() => _ColumnWidgetState(); } class _ColumnWidgetState extends State<ColumnWidget> { String _result = "顯示接收接據"; //BasicMessageChannel 調用原生方法並回調 按鈕點擊觸發事件 void basicChannelMethod(){ Map params = {"method":"test","context":"testValue","code": 200}; toolsBasicChannelMethodWithParams(params).then((result){ //result 原生回調結果 _result = result.toString(); print(result); }); setState(() { }); } //MethodChannel 調用原生方法並回調 按鈕點擊觸發事件 void methodChannelMethod() { //調用ChannelTools中的方法 參數一方法名 參數二、Map類型鍵值對參數 toolsMethodChannelMethodWithParams('methodChannelTest').then((result){ //result 原生回調結果 _result = result.toString(); }); setState(() { }); } static const eventChannel = const EventChannel('semf.datacvg.com/eventChannel'); //EventChannel 原生數據傳遞 按鈕點擊觸發事件 void eventChannelMethod(){ //data 原生 toolsEventChannelMethod((data){ _result = data; }); setState(() { }); } @override Widget build(BuildContext context) { // TODO: implement build return Center( child: Column( mainAxisAlignment:MainAxisAlignment.center, children: <Widget>[ RaisedButton.icon( icon: Icon(Icons.send), onPressed: basicChannelMethod, label: Text('BasicMessageChannel 調用原生方法並回調') ), RaisedButton.icon( icon: Icon(Icons.send), onPressed: methodChannelMethod, label: Text('MethodChannel 調用原生方法並回調') ), RaisedButton.icon( icon: Icon(Icons.send), onPressed: eventChannelMethod, label: Text('EventChannel 調用原生方法並回調') ), SizedBox( width: 300, child: Container( child: Text('flutter接收數據'+_result), ), ), ], ), ); } } //Toast.show("鑒權失敗!", context, duration: Toast.LENGTH_LONG, gravity: Toast.CENTER); /* iOS BasicMessageChannel原生實現方法 _basicMethodChannel = [FlutterBasicMessageChannel messageChannelWithName:@"semf.datacvg.com/Test" binaryMessenger:[flutter binaryMessenger]]; // 注冊方法等待flutter頁面調用 [_basicMethodChannel setMessageHandler:^(id _Nullable message, FlutterReply _Nonnull callback) { NSString *method=message[@"method"]; if ([method isEqualToString:@"test"]) { //調用原生自定義方法 //[weakSelf testMethod]; //返回flutter數據 NSMutableDictionary *dic = [NSMutableDictionary dictionary]; [dic setObject:@"basicMethodChannel 原生返回flutter的數據" forKey:@"message"]; [dic setObject: [NSNumber numberWithInt:200] forKey:@"code"]; [dic setObject: @"內容" forKey:@"context"]; callback(dic); } }]; --------------- iOS MethodChannel原生實現方法 _methodChannel = [FlutterMethodChannel methodChannelWithName:@"semf.datacvg.com/semf" binaryMessenger:[flutter binaryMessenger]]; [_methodChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { NSLog(@"%@", call.method); NSLog(@"%@", call.arguments); if ([call.method isEqualToString:@"methodChannelTest"]) { //[weakSelf testMethod]; //返回flutter數據 NSMutableDictionary *dic = [NSMutableDictionary dictionary]; [dic setObject:@"methodChannel 原生返回flutter的數據" forKey:@"message"]; [dic setObject: [NSNumber numberWithInt:200] forKey:@"code"]; [dic setObject: @"內容" forKey:@"context"]; result(dic); } }]; ---------------- iOS EventChannel 原生實現方法 <FlutterStreamHandler> FlutterEventChannel* eventChannle = [FlutterEventChannel eventChannelWithName:@"semf.datacvg.com/eventChannel" binaryMessenger:[flutter binaryMessenger]]; [eventChannle setStreamHandler:self]; 數據代理 FlutterStreamHandler - (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(FlutterEventSink)events {}//此處的arguments可以轉化為剛才receiveBroadcastStream("init")的名稱,這樣我們就可以一個event來監聽多個方法實例 - (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {} */