【问题标题】:How can I display a dialog whenever my stream gets a new value?每当我的流获得新值时,如何显示对话框?
【发布时间】:2020-05-11 10:52:10
【问题描述】:

我有以下集团供应商

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

但问题是每当包含此流构建器的小部件重建时,通知都会再次显示,因为满足条件,这不是我想要的,因为我只想显示一次通知。那么我该如何防止这种情况发生呢?感觉就像我有一个结构性问题,我就是想不通。

【问题讨论】:

    标签: flutter dart stream


    【解决方案1】:

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

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

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

    3. 您可以使用例如https://pub.dev/packages/get 包来显示对话框/从您的区域进行导航,而无需通知页面有关新状态的信息。

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

    【讨论】:

    • 选项 2 是否要求我的小部件是有状态的小部件?
    • MaterialApp中需要设置navigation key(一般是app的起点),然后根据这个key编写显示对话框的服务。我只是很有趣,使用 Stateful 小部件有什么问题?
    • @MikeOttink 你可以查看 3 选项源代码,以便更好地理解解决方案 2。3 只是 2 的打包解决方案
    • 好的,所以在我的应用程序中,我有一个嵌套在主材料应用程序中的材料应用程序。但这会使用 Get 生成错误。知道为什么以及如何解决它们吗?
    • 好的,它的工作,该死的速度......这个应用程序现在更快了
    猜你喜欢
    • 2017-08-10
    • 2011-02-09
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多