Bram  Vanbilsen
Bram Vanbilsen

Reputation: 6505

Flutter native plugin: Example with eventlisteners

I'm looking for an easy to follow example of eventlisteners with native plugins. So for example: The plugin that I'm writing has a lot of listeners that do something when an action failed or is completed. Those listeners can be written in native code, but how would I allow the end user, who writes dart code, to write their own custom listeners? So for example add another variable assignment in an onSuccess event?

I'm searching for a small example for Android and iOS.

---- EDIT ----
I'm working with this code 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;

And

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());
    }
  });
}

My onListen and onCancel methods are still empty. I'd like to setupgeoQueryQueryReadyEventChannel first . I'd like to send over data with this channel whenever onGeoQueryReady in the GeoQueryEventListener picks something up. How can I achieve this? My main problem is that I don't understand how I can link the GeoQueryEventListener in an onListen method to a local GeoQuery instance.

Upvotes: 4

Views: 6567

Answers (2)

Ankit
Ankit

Reputation: 135

Hope this will help...

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

The GeoFirePlugin look like :

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");
    }
}

Upvotes: 1

Matthew Smith
Matthew Smith

Reputation: 4637

Not sure if this will help but I recently wrote a plugin that has multiple event listeners: https://github.com/apptreesoftware/pusher_flutter. When I wrote it I used the Sensor plugin as a guide: https://github.com/flutter/plugins/tree/master/packages/sensors

The basics are for each listener you need to create a FlutterEventChannel and another class that implements FlutterStreamHandler.

In my example I create the 3 Channels and their StreamHandlers. I have one channel for listening for errors, one for connectivity changes and the last one for receiving messages. Each EventChannel has an identifier. In my dart code I create one event channel for each FlutterEventChannel I created in native code.

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

I then expose that API is Streams by using `receiveAsBroadcastStream:

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

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

So the end users API is:

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

Upvotes: 4

Related Questions