每当流获得新值时如何显示对话框?

时间:2020-05-11 10:52:10

标签: flutter dart stream

我有以下bloc提供商

class CloudMessagingBloc{
  StreamController<NotificationModel> _streamController = StreamController<NotificationModel>();
  Stream<NotificationModel> get stream => _streamController.stream;
  final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();

  CloudMessagingBloc() {
    if (Platform.isIOS) _firebaseMessaging.requestNotificationPermissions(IosNotificationSettings());
    _firebaseMessaging.configure(
      onMessage: (Map<String, dynamic> message) async {
        _streamController.add(NotificationModel.fromMap(message));
      },
      onLaunch: (Map<String, dynamic> message) async {
        _streamController.add(NotificationModel.fromMap(message));
      },
      onResume: (Map<String, dynamic> message) async {
        _streamController.add(NotificationModel.fromMap(message));
      },
    );
  }

  void dispose(){
    _streamController.close();
  }
}

并像这样实现它

  static Widget create() {
    return MultiProvider(
      providers: [
        Provider(create: (_) => DelayBloc(seconds: 2)),
        Provider(
          create: (_) => CloudMessagingBloc(),
          dispose: (BuildContext context, CloudMessagingBloc bloc) => bloc.dispose(),
          lazy: false,
        ),
      ],
      child: TheRootPage(),
    );
  }

在我的根页面无状态小部件中。但是现在我有一个问题,因为每当流发出新值时,我都希望显示一次对话框。因此,我为此强加了一个streambuilder,并且在添加新值时通知会正确显示

StreamBuilder(
  stream: cloudMessagingBloc.stream,
  builder: (BuildContext context, AsyncSnapshot<NotificationModel> snapshot) {
    if (snapshot.connectionState == ConnectionState.active && snapshot.hasData)
      SchedulerBinding.instance
          .addPostFrameCallback((_) => _showNotificationDialog(context, snapshot.data));

但是问题在于,只要重建包含此streambuilder的窗口小部件,由于满足条件(因为我只想要显示一次通知),所以再次显示通知,因为这不是我想要的。那么如何防止这种情况发生呢?感觉像我有一个结构性问题,只是无法解决。

1 个答案:

答案 0 :(得分:1)

我看到3种可能的解决方案:

  1. 您需要使用https://pub.dev/packages/equatable来检查它是否为新状态。这也来自ferangel(BLOC软件包的作者)。您可以在Google中找到带有Equitable和Bloc的示例。

  2. 您可以创建一个全局键,然后使用它来显示对话框(如果您具有全局键,则可以从中检索上下文,然后从bloc中调用dialogService.showMyDialog())。

    < / li>
  3. 例如,您可以使用https://pub.dev/packages/get包从您的集团显示对话框/进行导航,而无需通知Page有关新状态。

我个人更喜欢2或3。 但有时也使用第一个。