Search code examples
flutterpush-notificationfirebase-cloud-messagingdart-isolates

Set a callback accessible from an isolate in flutter


I'm trying to achieve the following: I'm using a top level background handler for firebase notifications. However I would like to add an optional callback to the main app isolate.

The objective is to trigger some UI refresh depending on the background notification received.

Since the background handler is spawned in its own isolate, the callback I'd like to use in my view won't get called as it is defined in another isolate...

Any suggestion?

Here is the footprint of my code

void onBackgroundNotification(){
  print('received');
  // Here want to call an optional callback
  PushService.instance.callback?.call();
  // however callback will be null because set from another isolate
}

class PushService {
  //Singleton pattern

  final Function() callback;
}

///in my view
...
void onInit(){
  PushService.instance.callback = _viewCallback;
}
void onDispose(){
  PushService.instance.callback = null;
}
void _viewCallback() {
  print('callback_called');
}

Solution

  • Ok guys!

    I found the solution in another Firebase Plugin readme (FirebaseDownloader) here: https://pub.dev/packages/flutter_downloader#update-download-progress

    I had to create a SendPort and use NotificationServer for the communication instead of a callback. My code footprint became this:

    void onBackgroundNotification(){
          print('received');
          // Here want to call an optional callback
          
          // This is used to send notification back to app if in background
          final send IsolateNameServer.lookupPortByName('communication_channel');
          send.send(message.data);
        }
        
        ///in my view
        ...
    
        final ReceivePort _receiveNotificationPort = ReceivePort();
        
        void onInit(){
          IsolateNameServer.registerPortWithName(
            _receiveNotificationPort.sendPort,
            'communication_channel',
          );
          _receiveNotificationPort.listen((dynamic data) {
            _myNotificationCallback(data);
          });
        }
    
        void onDispose(){
          IsolateNameServer.removePortNameMapping('communication_channel');
        }
    
        void _myNotificationCallback(dynamic data) {
          print(data.value);
        }