2

是否有正确的方法可以从 Flutter 应用程序中的“根”页面或位置收听流/范围模型,并在收到一些数据后在任何当前打开的页面(可能不是主页)上显示适当的通知(例如 Snackbar) )?

我希望能够在整个应用程序中显示某些通知,而不仅仅是逐页显示。

在这里,我有一个主页,它是我的应用程序初始页面,它开始监听从上下文中检索到的 scoped_model 的流,并且无论用户正在访问哪个页面,只要接收到数据都会显示一个对话框。

class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {

MyService service  = ScopedModel.of<MyService>(context);

service.events.stream.listen((data) {
  showDialog<String>(
      context: context,
      barrierDismissible: true, // dialog is dismissible with a tap on the barrier
      builder: (BuildContext context) {
        return AlertDialog(
            title: Text('An Event has Occurred'),
            content: Text('$data'));});
});

return Scaffold(
//Navigator Push Routes - Page 1 / Page 2 / Page 3 / etc
);}

这种工作,但真的感觉不正确 - 有没有人这样做过谁可以提供更好的解决方案?

我可以为每个页面添加一个类似的侦听器,但这似乎真的没必要

4

2 回答 2

0

我做过类似的事情。尽管您确实应该将它放在有状态的小部件中,但在 initstate 中添加侦听器,而不是在无状态小部件的小部件构建方法中。

于 2019-06-06T15:02:01.933 回答
0

++++ 2019 年 7 月更新 ++++

我写了一个支持应用程序范围消息显示的包。

EZ Flutter 是小部件、包和许多有用的东西的集合,混合在一个小框架中。目的是从头开始提供标准功能。EZ Flutter 支持通过一行代码从应用程序内的任何位置向用户显示消息。

Github:https ://github.com/Ephenodrom/EZ-Flutter

dependencies:
  ez_flutter: ^0.2.0

查看文档如何使用不同的配置。

https://github.com/Ephenodrom/EZ-Flutter/blob/master/documentation/GLOBAL_MESSAGE.md

++++老答案++++

也许这个例子会有所帮助:

https://github.com/Ephenodrom/Flutter-Advanced-Examples/tree/master/lib/examples/globalMessage

这个想法是有一个消息包装器小部件,它显示带有被推送到 BLOC 中的快餐栏的消息。

class GlobalMessageWrapper extends StatefulWidget {
  final Widget child;

  GlobalMessageWrapper(this.child);
  @override
  _GlobalMessageWrapperState createState() => _GlobalMessageWrapperState();
}

class _GlobalMessageWrapperState extends State<GlobalMessageWrapper> {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
        initialData: null,
        stream: BlocProvider.of<GlobalBloc>(context).messageBloc.messageStream,
        builder: (BuildContext context, AsyncSnapshot<Message> snapshot) {
          Message msg = snapshot.data;
          if (msg != null) {
            WidgetsBinding.instance
                .addPostFrameCallback((_) => _showMessage(msg));
          }
          return Container(child: widget.child);
        });
  }

  void _showMessage(Message message) {
    Color color = Colors.grey;

    switch (message.type) {
      case "success":
        color = Colors.green;
        break;
      case "info":
        color = Colors.blue;
        break;
      case "warning":
        color = Colors.orange;
        break;
      case "error":
        color = Colors.red;
        break;
      default:
    }
    SnackBar bar = SnackBar(
        content: Padding(
          padding: const EdgeInsets.only(bottom: 50.0),
          child: Text(message.text),
        ),
        backgroundColor: color);

    Scaffold.of(context)
      ..hideCurrentSnackBar()
      ..showSnackBar(bar);
  }
}

要在您的应用程序中全局使用 Wrapper,请将其放在小部件树的顶部。您可以将它放在 main.dart 文件中的 MaterialApp Widget 下。

于 2019-06-19T14:11:31.580 回答