Overview
Flutter-Native 消息通道一共有以下三种,在日常开发的过程中我们可能使用的MethodChannel
相对比较多一些。
而这三种消息通道都是在Flutter
的flutter/services.dart
库中提供,具体使用哪种方式,需要根据具体的业务来决定。
MethodChannel
:用于单向调用,Flutter端可以调用原生平台的方法,原生端可以返回结果给Flutter端。
EventChannel
:用于双向通信,Flutter端可以监听原生平台发出的事件,原生端也可以发送事件给Flutter端。
BasicMessageChannel
:用于传递任意类型的消息,可以实现双向通信。Flutter端和原生端可以互相发送和接收不同类型的消息。
MethodChannel
使用MethodChannel
可以实现Flutter与原生平台的单向通信,Flutter端可以调用原生平台的方法,并接收返回的结果。
在实际开发中,我们获取设备的信息、或者唤起原生的相机、相册等功能都会使用MethodChannel
实现。
Flutter端实现
需要在Flutter端创建一个MethodChannel,具体示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import 'package:flutter/services.dart';
class YourMethodChannel { const platform = const MethodChannel('com.example.flutter_native_communication');
Future<void> callNativeMethod() async { try { final String result = await platform.invokeMethod('getPlatformVersion'); print('Response from native code: $result'); } on PlatformException catch (e) { print('Error: ${e.message}'); } } }
|
安卓端实现
在Android平台上实现相应的方法。具体我们可以创建一个插件类来处理Flutter调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package com.example.flutter_channel_plugin;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result;
/// MethodChannel:用于单向调用,Flutter端可以调用原生平台的方法,原生端可以返回结果给Flutter端。 public class FlutterChannelPlugin implements FlutterPlugin, MethodCallHandler { private MethodChannel channel;
@Override public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "flutter_channel_plugin"); channel.setMethodCallHandler(this); }
@Override public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { if (call.method.equals("getPlatformVersion")) { result.success("Android " + android.os.Build.VERSION.RELEASE); } else { result.notImplemented(); } }
@Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { channel.setMethodCallHandler(null); } }
|
iOS实现
在iOS端我们同样需要创建个插件类来处理Flutter的调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| #import <Flutter/Flutter.h>
@interface FlutterChannelPlugin () <FlutterPlugin>
@property (nonatomic, strong) FlutterMethodChannel *channel;
@end
@implementation FlutterChannelPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { // 创建插件实例并注册 FlutterChannelPlugin* instance = [[FlutterChannelPlugin alloc] init]; [instance setupMethodChannel:registrar]; }
- (void)setupMethodChannel:(NSObject<FlutterPluginRegistrar> *)registrar { // 创建FlutterMethodChannel实例 self.channel = [FlutterMethodChannel methodChannelWithName:@"com.example.flutter_native_communication" binaryMessenger:[registrar messenger]]; // 设置回调函数 __weak typeof(self) weakSelf = self; [self.channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { [weakSelf handleMethodCall:call result:result]; }]; }
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { if ([call.method isEqualToString:@"getPlatformVersion"]) { NSString* platform = [NSString stringWithFormat:@"iOS %@", [[UIDevice currentDevice] systemVersion]]; result(platform); } else { result(FlutterMethodNotImplemented); } }
@end
|
EventChannel
EventChannel
基本用于Flutter
与原生平台之间进行双向通信,允许原生平台向 Flutter
发送事件。
Flutter端实现
在Flutter端,我们需要使用Dart语言中创建一个EventChannel的实例,并设置事件监听器,具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import 'package:flutter/services.dart';
class YourEventChannel { // 创建 EventChannel 实例 EventChannel eventChannel = EventChannel('com.example.flutter_native_communication/events');
// 监听来自原生平台的事件 StreamSubscription subscription; subscription = eventChannel.receiveBroadcastStream().listen((event) { // 处理来自原生平台的事件 print('Received event: $event'); });
// 在不需要时取消监听 subscription.cancel(); }
|
安卓端实现
在安卓端,我们同样需要创建一个EventChannel
实例,并通过该实例发送事件到 Flutter,具体代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| package com.example.flutter_channel_plugin;
import android.content.Context; import io.flutter.embedding.engine.FlutterEngine; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.EventChannel.EventSink; import io.flutter.plugin.common.EventChannel.StreamHandler;
public class FlutterEventChannelPlugin implements StreamHandler { private static final String EVENT_CHANNEL = "com.example.flutter_native_communication/events"; private EventSink eventSink;
public static void register(Context context, BinaryMessenger messenger) { FlutterEventChannelPlugin plugin = new FlutterEventChannelPlugin(); EventChannel eventChannel = new EventChannel(messenger, EVENT_CHANNEL); eventChannel.setStreamHandler(plugin); }
@Override public void onListen(Object arguments, EventSink eventSink) { this.eventSink = eventSink;
// 将事件发送到Flutter端 sendMessageToFlutter(); }
@Override public void onCancel(Object arguments) { // 取消监听 eventSink = null; }
private void sendMessageToFlutter() { // 模拟发送事件到Flutter端 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
if (eventSink != null) { eventSink.success("Event: " + i); } } } }).start(); } }
|
iOS端实现
在iOS端,我们同样也需要创建一个EventChannel
实例,并通过该实例发送事件到 Flutter,具体代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| @interface FlutterEventChannelPlugin()<FlutterStreamHandler>
@property (nonatomic, strong) FlutterEventChannel *eventChannel; @property (nonatomic, copy) FlutterEventSink eventSink;
@end
@implementation FlutterEventChannelPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { FlutterEventChannelPlugin* instance = [[FlutterEventChannelPlugin alloc] init]; [instance setupEventChannel:registrar]; }
- (void)setupEventChannel:(NSObject<FlutterPluginRegistrar> *)registrar { // 创建 FlutterEventChannel 实例 self.eventChannel = [FlutterEventChannel eventChannelWithName:@"com.example.flutter_native_communication/events" binaryMessenger:[registrar messenger]]; [self.eventChannel setStreamHandler:self]; }
// 在某个地方调用这个方法向 Flutter 发送事件 - (void)sendEventToFlutter:(NSString*)event { if (self.eventSink) { self.eventSink(event); } }
- (void)stopListening { // 在这里添加停止监听事件的逻辑 }
- (void)sendEvent:(id)eventData { if (self.eventSink) { self.eventSink(eventData); } }
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(FlutterEventSink)events { self.eventSink = events; return nil; }
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments { self.eventSink = nil; // 在这里添加取消监听事件的逻辑 return nil; }
@end
|
BasicMessageChannel
BasicMessageChannel
可以进行原生和Flutter双向通信。
Flutter端实现
在Flutter我们需要使用Dart语言创建个BasicMessageChannel
实例,并设置消息监听器,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import 'package:flutter/services.dart';
class YourBasicMessageChannel { static const String _channelName = 'your_basic_message_channel_name'; final MethodChannel _methodChannel = MethodChannel(_channelName);
Future<dynamic> sendMessage(dynamic message) async { final dynamic response = await _methodChannel.invokeMethod('sendMessage', message); return response; }
void setMessageHandler(Future<dynamic> Function(dynamic) handler) { _methodChannel.setMethodCallHandler((MethodCall call) { if (call.method == 'receiveMessage') { return handler(call.arguments); } return handler(null); }); } }
|
Android端实现
在Android端,我们同样需要创建一个BasicMessageChannel
实例,并通过该实例发送消息到 Flutter,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.example.flutter_channel_plugin;
import android.content.Context; import io.flutter.plugin.common.BasicMessageChannel; import io.flutter.plugin.common.StringCodec; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MessageCodec;
public class FlutterBasicChannelPlugin { private static final String CHANNEL_NAME = "com.example.flutter_native_communication/basic_message";
public static void register(Context context, BinaryMessenger messenger) { BasicMessageChannel<String> messageChannel = new BasicMessageChannel<>(messenger, CHANNEL_NAME, StringCodec.INSTANCE); messageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler<String>() { @Override public void onMessage(String message, BasicMessageChannel.Reply<String> reply) { // 处理来自Flutter端的消息 String replyMessage = "Received message: " + message; reply.reply(replyMessage); } }); } }
|
iOS端实现
在Android端,我们也需要创建一个BasicMessageChannel
实例,并通过该实例发送消息到 Flutter,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| #import <Flutter/Flutter.h> @interface NativeCommunicationPlugin () <FlutterMessageListener>
@property (nonatomic, strong) FlutterBasicMessageChannel *messageChannel;
@end
@implementation NativeCommunicationPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { // 创建插件实例并注册 NativeCommunicationPlugin* instance = [[NativeCommunicationPlugin alloc] init]; [instance setupMessageChannel:registrar]; }
- (void)setupMessageChannel:(NSObject<FlutterPluginRegistrar> *)registrar { // 创建 FlutterBasicMessageChannel 实例 self.messageChannel = [FlutterBasicMessageChannel messageChannelWithName:@"com.example.flutter_native_communication/basic_message" binaryMessenger:[registrar messenger]]; // 设置消息处理器 __weak typeof(self) weakSelf = self; [self.messageChannel setMessageHandler:^(id message, FlutterReply reply) { // 处理来自 Flutter 的消息 NSLog(@"Received message: %@", message); // 回复消息给 Flutter reply(@"Reply from iOS"); }]; }
// 在某个地方调用这个方法向 Flutter 发送消息 - (void)sendMessageToFlutter:(NSString *)message { [self.messageChannel sendMessage:message reply:^(id reply) { // 处理来自 Flutter 的回复消息 NSLog(@"Received reply: %@", reply); }]; }
@end
|
参考资料