在flutter插件开发中,EventChannel
与MethodChannel
是两个不可避免的类。我们要了解它,最好先记住它通常用来干嘛。
MethodChannel用通俗的语言来描述它的作用就是,当你像在flutter端调用native功能的时候,可以用它。
EventChannel用通俗的语言来描述就是,当native想通知flutter层一些消息的时候,可以用它。
要用这两个桥梁,首先要明白它是怎么打通的,我们应该对这段代码不陌生:
public static void registerWith(Registrar registrar) {
TipFlutterImageViewPlugin plugin = new TipFlutterImageViewPlugin(registrar, registrar.context());
final MethodChannel channel = new MethodChannel(registrar.messenger(), "com.tencent.igame/flutter_image_view_method");
final EventChannel eventChannel = new EventChannel(registrar.messenger(), "com.tencent.igame/flutter_image_view_event");
channel.setMethodCallHandler(plugin);
eventChannel.setStreamHandler(plugin);
}
在你create一个插件工程的时候,flutter脚手架是会为你生成一个名字为XXXPlugin的类,里面就有这么一个registerWith
的方法。两个Channel都是在这里注册的。那么,这段代码在何处被调用的呢?我们可以看看插件代码的android工程;
public final class GeneratedPluginRegistrant {
public static void registerWith(PluginRegistry registry) {
if (alreadyRegisteredWith(registry)) {
return;
}
XXXPlugin.registerWith(registry.registrarFor("com.tencent.igame.tip_flutter_image_view.TipFlutterImageViewPlugin"));
}
private static boolean alreadyRegisteredWith(PluginRegistry registry) {
final String key = GeneratedPluginRegistrant.class.getCanonicalName();
if (registry.hasPlugin(key)) {
return true;
}
registry.registrarFor(key);
return false;
}
}
然后这个静态方法在MainActivity的onCreate中被调用了。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
到registerWith被调用为止,两个Channel被注册了而已,它还并没有和flutter关联起来,此时我们也不急,先看看,我们可以了解到的是registerWith被调用了一次,因此XXXPlugin只有一个实例,MethodChannel和EventChannel是其成员,也只有一个。好,接下来,flutter关联上这了两个Channel。
eventChannel = new EventChannel('com.tencent.igame/flutter_image_view_event')
.receiveBroadcastStream(url)
.map((dynamic event) => _parseState(event));
methodChannel = new MethodChannel('com.tencent.igame/flutter_image_view_method');
一般可以放在flutter页面的initState做。
此时,我们flutter调用原生可以使用
//flutter端
_channel.invokeMethod('method',{})
//原生端
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("create")) {
//xxxx
}
}
此时,原生发送消息到flutter可以
//原生端发送消息
public void onListen(Object args, EventChannel.EventSink eventSink) {
eventSink.success()
//eventSink.error();
}
//flutter端接收消息
eventChannel.listen((data) {
//xxxx
});
至此,整个流程打通了,如果就这样完了的话,这篇文章可以改名叫做《EventChannel与MethodChannel的使用》了。
EventChannel其实是基于MethodChannel实现的,不信,我们可以看源码:
Stream<dynamic> receiveBroadcastStream([ dynamic arguments ]) {
final MethodChannel methodChannel = MethodChannel(name, codec);
StreamController<dynamic> controller;
controller = StreamController<dynamic>.broadcast(onListen: () async {
defaultBinaryMessenger.setMessageHandler(name, (ByteData reply) async {
if (reply == null) {
controller.close();
} else {
try {
controller.add(codec.decodeEnvelope(reply));
} on PlatformException catch (e) {
controller.addError(e);
}
}
return null;
});
try {
await methodChannel.invokeMethod<void>('listen', arguments);
} catch (exception, stack) {
//xxx/
}, onCancel: () async {
defaultBinaryMessenger.setMessageHandler(name, null);
try {
await methodChannel.invokeMethod<void>('cancel', arguments);
} catch (exception, stack) {
//xxxx
});
return controller.stream;
}
}
说的没错把,这里就是通过methodChannel去调用在原生那边实现的方法:
onListen(Object args, EventChannel.EventSink eventSink)
onCancel(Object args)
好的,我们的认识更进了一步,那么,在问一个问题,如果多次注册同一个EventChannel并listen,那么每个都有效吗?
就直接说答案了,并不是每个都有效,有效的只是最后注册的那一个。
还记得我们的plugin的实例只有一个吗?还记得其中的成员EventChannel也只有一个吗?那么,在flutter端调用多次
eventChannel = new EventChannel('com.tencent.igame/flutter_image_view_event')
.receiveBroadcastStream(url)
.map((dynamic event) => _parseState(event));
显然只有最后一次会生效,其他是收不到消息的。
这个当然是没问题的,多个EventChannel只需要在registerWith方法中注册一一进行注册就OK了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。