如何在 Flutter 中显示流中的 Snackbar?

mFe*_*ein 2 stream flutter

我想显示SnackBar一次Stream发送String新的String.

我尝试将 a 放在StreamBuildera 内StatefulWidget,以便能够调用Scaffold.of()(因为现在是另一个context)。但后来我得到这个错误:

构建 StreamBuilder(dirty, state: _StreamBuilderBaseState>#7f258) 时抛出以下断言:构建期间调用 setState() 或 markNeedsBuild()。该 Scaffold 小部件无法标记为需要构建,因为框架已经在构建小部件的过程中。仅当小部件的祖先之一当前正在构建时,才可以将其标记为需要在构建阶段构建。允许此异常,因为框架在子窗口之前构建父窗口小部件,这意味着将始终构建脏后代。否则,框架可能不会在此构建阶段访问此小部件。调用 setState() 或 markNeedsBuild() 的小部件是: Scaffold(dependencies: [_LocalizationsScope-[GlobalKey#0e1f6], Directionality, _InheritedTheme, MediaQuery], state: ScaffoldState#3f2aa(tickers: Tracking 2tickers)) 小部件当进行有问题的调用时,当前正在构建的是: StreamBuilder(dirty, state: _StreamBuilderBaseState>#7f258)

我该如何解决这个问题?

这是显示问题的简单代码片段:

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: TestHome(),
    );
  }
}

class TestHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: StreamSnackbar(),
    );
  }
}

class StreamSnackbar extends StatefulWidget {
  @override
  _StreamSnackbarState createState() => _StreamSnackbarState();
}

class _StreamSnackbarState extends State<StreamSnackbar> {
  final status = StreamController<String>();

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              onPressed: () {
                status.add('Test');
              },
              child: Text('Press me to trigger the Snackbar!'),
            ),
            StreamBuilder<String>(
              stream: status.stream,
              builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
                if (snapshot.hasData) {
                  Scaffold.of(context)
                      .showSnackBar(SnackBar(content: Text(snapshot.data)));
                }
                return Container(
                  height: 0,
                  width: 0,
                ); // just because we need to return a Widget
              },
            ),
          ],
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

Gün*_*uer 5

没有必要使用StreamBuilder. 显示无论如何都SnackBar必须在同步执行之外完成build()

@override
void initState() {
  super.initState();
  status.stream.forEach((e) =>
    Scaffold.of(context)
        .showSnackBar(SnackBar(content: Text(e))));
}

@override
void dispose() {
  status.close();
  super.dispose();
}
Run Code Online (Sandbox Code Playgroud)

  • 好点,我想我已经陷入了这些模式中。我正在考虑使用 `WidgetsBinding.instance.addPostFrameCallback() `,但想看看是否有更好的选择,谢谢 Gunter! (2认同)