FlutterFire后台隔离通信

Son*_*ieu 1 dart-isolates firebase flutter firebase-cloud-messaging

我正在开发一个 VoIP 应用程序,但后台处理程序有问题。我想要的是:发送类型为“call”的推送,然后应用程序将显示呼叫 UI,稍后如果收到推送类型“hangup”,应用程序将关闭该呼叫 UI。

在后台处理程序中,我使用单例全局类来通知 StreamController 的挂断事件,并且 CallScreen 小部件将侦听该流以关闭自身。

然后我发现 flutterfire 将为后台处理程序启动另一个隔离(关闭屏幕),因此它将创建另一个单例类 -> 我无法使用这个新的单例类关闭我的 CallScreen UI。

是否可以用 flutterfire 的背景隔离做这样的事情?

伪代码示例:

class SingletonGlobal {
  /// singleton class

  final hangUpStreamController = StreamController<HangUpEvent>.broadcast();

  void addHangupEvent(HangUpEvent event) {
    hangUpStreamController.add(event);
  }
}

class CallScreen extends StatefulWidget {
  //// ...
    @override
    void initState() {
      SingletonGlobal().hangUpStreamController.stream.listen((event) => closeCallUI(event));
    }
}

Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  await appInit();

  if (message.data.type = 'hangup') {
    SingletonGlobal().addHangupEvent(hangUpEvent);
}
Run Code Online (Sandbox Code Playgroud)

更新

我尝试了 Nitrodon 的解决方案。但正如我提到的, _firebaseMessagingBackgroundHandler 将创建我的SingleGlobal类的另一个实例。我不知道为什么。

收到 firebase 后台处理程序后再次打印“SingletonGlobal#internal”。这意味着它重新创建了 SingletonGlobal。

class SingletonGlobal {
  /// singleton class
  static SingletonGlobal? _instance;
  final _receivePort = ReceivePort();

  factory SingletonGlobal() => _instance ?? SingletonGlobal._internal();


  SingletonGlobal._internal() {
    print('SingletonGlobal#internal');
    IsolateNameServer.registerPortWithName(_receivePort.sendPort, 'global_singleton');
    _receivePort.listen((message) => hangUpStreamController.add);

    _instance = this;
  }

}
Run Code Online (Sandbox Code Playgroud)

小智 5

隔离群之间有多种沟通方式。在这种情况下,由于您只需要监听主isolate上的事件,因此您可以注册一个端口来接收来自后台isolate的hangup事件:

class SingletonGlobal {
  // Whatever private constructor you're using for this singleton
  SingletonGlobal._() {
    IsolateNameServer.registerPortWithName(_receivePort.sendPort, 'some port name');
    _receivePort.listen(hangUpStreamController.add);
  }

  final hangUpStreamController = StreamController<HangUpEvent>.broadcast();

  final _receivePort = ReceivePort();

  void addHangupEvent(HangUpEvent event) {
    hangUpStreamController.add(event);
  }
}

void _firebaseMessagingBackgroundHandler(RemoteMessage message) {
  // Do not try to access SingletonGlobal here.

  if (message.data.type = 'hangup') {
    // Since the background isolate is still in the same process, you
    // can send objects (which are copied) instead of just basic messages.
    IsolateNameServer.lookupPortByName('some port name')?.send(hangUpEvent);
  }
}
Run Code Online (Sandbox Code Playgroud)