Home > database >  How to invoke a listener from another listener?
How to invoke a listener from another listener?

Time:09-05

I'm using in_app_purchase package and I need to convert/map listener which is listening for List<PurchaseDetails> to another listener as shown below:

class Foo {
  Foo() {
    InAppPurchase.instance.purchaseStream.listen(_listener);
  }

  void _listener(List<PurchaseDetails> list) {
    // How to pass these ids to `addListener()`
    final List<String> ids = list.map((e) => e.productID).toList();
  }

  void addListener(void Function(List<String>) f) {}
}

This is how I want to use my listener

void main() {
  Foo().addListener((List<String> ids) {});
}

CodePudding user response:

Despite what your code comment says, I think what you're really asking for is for the internal _listener to invoke the callback that was previously passed as an argument to addListener (and not for _listener to call addListener directly, which it could just do directly).

Just have addListener save the callback to a member variable and let _listener invoke that:

class Foo {
  void Function(List<String>)? _listener;
  
  Foo() {
    InAppPurchase.instance.purchaseStream.listen(_internalListener);
  }

  void _internalListener(List<PurchaseDetails> list) {
    var listener = _listener;
    if (listener == null) {
      return;
    }

    final List<String> ids = list.map((e) => e.productID).toList();
    listener(ids);
  }

  void addListener(void Function(List<String>) f) => _listener = f;
}

If you want callers to be able to call addListener multiple times to register multiple callbacks, you would need to store them in a collection (and provide a mechanism to unregister callbacks):

class Foo {
  final _listenerMap = <Object, void Function(List<String>)>{};
  
  Foo() {
    InAppPurchase.instance.purchaseStream.listen(_internalListener);
  }

  void _internalListener(List<PurchaseDetails> list) {
    if (_listenerMap.isEmpty) {
      return;
    }

    final List<String> ids = list.map((e) => e.productID).toList();
    for (var listener in _listenerMap.values) {
      listener(ids);
    }
  }

  Object addListener(void Function(List<String>) f) {
    var token = Object();
    _listenerMap[token] = f;
    return token;
  }
  
  void removeListener(Object token) {
    _listenerMap.remove(token);
  }
}
  • Related