Flutter 原生插件:事件监听器示例

Posted

技术标签:

【中文标题】Flutter 原生插件:事件监听器示例【英文标题】:Flutter native plugin: Example with eventlisteners 【发布时间】:2017-09-17 11:24:30 【问题描述】:

我正在寻找一个易于理解的带有本机插件的事件监听器示例。例如:我正在编写的插件有很多侦听器,它们会在操作失败或完成时执行某些操作。这些侦听器可以用本机代码编写,但是我如何允许编写 dart 代码的最终用户编写他们自己的自定义侦听器?那么例如在onSuccess 事件中添加另一个变量赋值?

我正在寻找适用于 androidios 的小示例。

---- 编辑 ---- 我正在使用此代码 atm:

public static void registerWith(Registrar registrar) 
    final MethodChannel methodChannelGeoFire = new MethodChannel(registrar.messenger(), "com.bram.vanbilsen.geofire.GeoFire");
    final MethodChannel methodChannelGeoQuery = new MethodChannel(registrar.messenger(), "com.bram.vanbilsen.geofire.GeoQuery");
    final EventChannel geoQueryKeyEnteredEventChannel = new EventChannel(registrar.messenger(), "com.bram.vanbilsen.geofire.keyEnteredChannel");
    final EventChannel geoQueryKeyExitedEventChannel = new EventChannel(registrar.messenger(), "com.bram.vanbilsen.geofire.keyExitedChannel");
    final EventChannel geoQueryKeyMovedEventChannel = new EventChannel(registrar.messenger(), "com.bram.vanbilsen.geofire.keyMovedChannel");
    final EventChannel geoQueryQueryReadyEventChannel = new EventChannel(registrar.messenger(), "com.bram.vanbilsen.geofire.queryReadyChannel");
    final EventChannel geoQueryQueryErrorEventChannel = new EventChannel(registrar.messenger(), "com.bram.vanbilsen.geofire.queryErrorChannel");
    final GeofirePlugin instance = new GeofirePlugin(registrar.activity());
    geoQueryKeyEnteredEventChannel.setStreamHandler(instance);
    geoQueryKeyExitedEventChannel.setStreamHandler(instance);
    geoQueryKeyMovedEventChannel.setStreamHandler(instance);
    geoQueryQueryReadyEventChannel.setStreamHandler(instance);
    geoQueryQueryErrorEventChannel.setStreamHandler(instance);
    methodChannelGeoFire.setMethodCallHandler(instance);
    methodChannelGeoQuery.setMethodCallHandler(instance);


GeofirePlugin(Activity activity) 
  this.activity = activity;


private final Activity activity;

if (call.method.equals("addGeoQueryEventListener")) 
  String refPath = call.argument("refPath");
  DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
  GeoFire geofire = new GeoFire(ref);
  List<Double> center = call.argument("center");
  double radius = call.argument("radius");
  GeoQuery query = geofire.queryAtLocation(new GeoLocation(center.get(0), center.get(1)), radius);
  query.addGeoQueryEventListener(new GeoQueryEventListener() 
    @Override
    public void onKeyEntered(String key, GeoLocation location) 
      System.out.println("entered");
    

    @Override
    public void onKeyExited(String key) 
      System.out.println("exited");
    

    @Override
    public void onKeyMoved(String key, GeoLocation location) 
      System.out.println("moved");
    

    @Override
    public void onGeoQueryReady() 

    

    @Override
    public void onGeoQueryError(DatabaseError error) 
      System.out.println(error.getMessage());
    
  );

我的 onListenonCancel 方法仍然是空的。我想先设置geoQueryQueryReadyEventChannel。每当GeoQueryEventListener 中的onGeoQueryReady 接收到某些内容时,我都想通过此通道发送数据。我怎样才能做到这一点?我的主要问题是我不明白如何将onListen 方法中的GeoQueryEventListener 链接到本地​​GeoQuery 实例。

【问题讨论】:

【参考方案1】:

不确定这是否会有所帮助,但我最近编写了一个具有多个事件侦听器的插件:https://github.com/apptreesoftware/pusher_flutter。当我写它时,我使用传感器插件作为指南:https://github.com/flutter/plugins/tree/master/packages/sensors

基础知识是为每个侦听器创建一个 FlutterEventChannel 和另一个实现 FlutterStreamHandler 的类。

在我的示例中,我创建了 3 个通道及其 StreamHandler。我有一个用于侦听错误的通道,一个用于连接更改,最后一个用于接收消息。每个 EventChannel 都有一个标识符。在我的 dart 代码中,我为在本机代码中创建的每个 FlutterEventChannel 创建一个事件通道。

_connectivityEventChannel =
        new EventChannel('plugins.apptreesoftware.com/pusher_connection');
_messageChannel =
        new EventChannel('plugins.apptreesoftware.com/pusher_message');
_errorChannel =
        new EventChannel('plugins.apptreesoftware.com/pusher_error');

然后,我使用 `receiveAsBroadcastStream: 公开该 API 是 Streams:

Stream<PusherMessage> get onMessage =>
      _messageChannel.receiveBroadcastStream().map(_toPusherMessage);

Stream<PusherError> get onError =>
      _errorChannel.receiveBroadcastStream().map(_toPusherError);

所以最终用户 API 是:

pusher.onMessage.listen((m) => doSomething(m));
pusher.onError.listen((e) => doSomethingWithError(m));

【讨论】:

你能更新第一个链接吗?它下来了。我想我明白了!但我很想先看看你的项目 :) 抱歉,链接已修复。 也许是个愚蠢的问题,但EventChannel 构造函数中的字符串是您选择的字符串,在本机代码和 dart 代码中都相同吗? 是的,名称必须相同。这是文档docs.flutter.io/javadoc/io/flutter/plugin/common/… 仍在努力使用onListen 方法。我在原始问题中添加了一些代码。【参考方案2】:

希望这会有所帮助...

EventChannel eventChannelService = new 
        EventChannel(registrar.messenger(), "com.xyz");
eventChannelService.setStreamHandler(
        new GeofirePlugin(registrar.activity()));

GeoFirePlugin 看起来像:

public class GeofirePlugin implements EventChannel.StreamHandler 

    @Override
    public void onListen(Object o, final EventChannel.EventSink eventSink) 
        Log.e("Success", "cancelling listener");
    

    @Override
    public void onCancel(Object o) 
        Log.e("Error", "cancelling listener");
    

【讨论】:

以上是关于Flutter 原生插件:事件监听器示例的主要内容,如果未能解决你的问题,请参考以下文章

vue创建自定义组件并监听原生事件

flutter 中监听滑动事件

flutter学习-事件监听

Flutter 监听 Stateless Widget 上的生命周期事件?

通过 onclick 原生方法 VueJs 监听事件点击

25.Flutter的ListView监听滚动事件之ScrollController