前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >flutter插件开发需要了解的EventChannel与MethodChannel

flutter插件开发需要了解的EventChannel与MethodChannel

原创
作者头像
brzhang
发布2020-01-08 19:24:51
5.8K0
发布2020-01-08 19:24:51
举报
文章被收录于专栏:玩转全栈玩转全栈

在flutter插件开发中,EventChannelMethodChannel是两个不可避免的类。我们要了解它,最好先记住它通常用来干嘛。

MethodChannel用通俗的语言来描述它的作用就是,当你像在flutter端调用native功能的时候,可以用它。

EventChannel用通俗的语言来描述就是,当native想通知flutter层一些消息的时候,可以用它。

这两个channel是如何打通的

要用这两个桥梁,首先要明白它是怎么打通的,我们应该对这段代码不陌生:

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。

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的猫腻

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(&#39;com.tencent.igame/flutter_image_view_event&#39;)
        .receiveBroadcastStream(url)
        .map((dynamic event) => _parseState(event));

显然只有最后一次会生效,其他是收不到消息的。

EventChannel可以有多个吗?

这个当然是没问题的,多个EventChannel只需要在registerWith方法中注册一一进行注册就OK了。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 这两个channel是如何打通的
    • flutter连接上Channel
      • EventChannel的猫腻
      • EventChannel可以有多个吗?
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档