我正在构建一个
Flutter-Plugin
,它提供了多个 UI-Widgets
来与本机(Android/iOS)库进行交互。 Flutter 端的库更新和/或状态更改通过 Events
委托,通过 Flutter EventChannel 委托给 Flutter。
这工作正常,但是我想将 several 侦听器添加到同一频道。但每次我想注册第二个侦听器时,第一个侦听器都会被取消(调用
StreamHandler.onCancel()
)。
private var channel01:EventChannel.EventSink ?= null
private var channel02:EventChannel.EventSink ?= null
//...
private var channel06:EventChannel.EventSink ?= null
//One EventChannel for every UI-Widget?!?!
EventChannel(registrar.messenger(), EVENT_CHANNEL_MAIN_SCREEN, JSONMethodCodec.INSTANCE).setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
L.d("Listener attached for channel 01")
postEvent(MyEvent("Send some data on attach"))
channel01 = events
}
override fun onCancel(p0: Any?) {
L.d("Listener detached for channel 01")
channel01 = null
}
})
//Trigger some data via flutter stream from Android/iOS to Flutter
fun postEvent(event: MyEvent) {
activity.runOnUiThread {
channel01?.success(event)
channel02?.success(event)
}
}
目前我为每个 UI-Widget 使用一个 EventChannel,但我想还有更好的方法吗?
顺便说一句,我在 Flutter 中使用了
Inherited Widget
作为 DataProvider,它是 EventChannel
的唯一侦听器,并将更改委托给树,但是由于“架构指南”,这是不可能的
问题
不可能将多个侦听器附加到一个通道。
合适的解决方案:将 EventChannel 附加到一个(继承)小部件中,在树中提升此小部件并使用 fluttersetState
逻辑来更新您的小部件。
BehaviorSubject
,因为它将向任何新侦听器报告最新值)。伪代码可能如下所示:
import 'package:rxdart/rxdart.dart';
StreamSubscription? _heartRateSub;
final _streamController = BehaviorSubject<MyModel>();
@override
Stream<MyModel> myStream() {
_streamSub ??= heartRateChannel.receiveBroadcastStream().listen((dynamic event) {
if (event is String) {
// process the event
_streamController.add(event);
}
})
..onError((Object error) {
// handle the error
});
_streamController.onCancel = () async {
await _streamSub?.cancel();
_streamSub = null;
};
return _streamController.stream;
}
这样,在我的 Dart 插件代码中就可以维护对事件通道的订阅一次。一旦所有侦听器取消对流的订阅,事件通道订阅也会被取消。