6

我正在尝试在流构建器中导航,但出现此错误:“在构建期间调用了 setState() 或 markNeedsBuild()。”。如果我在按下的按钮内调用导航,它可以工作,但不能仅在条件内使用它。我被困住了。有一些代码向您展示。

Widget build(BuildContext context) {
    return Scaffold(
      body: StreamBuilder(
        stream:
            Firestore.instance.collection('rooms').document(pinid).snapshots(),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.hasData) {
            if ((snapshot.data['Votes'][0] + snapshot.data['Votes'][1]) >=
                snapshot.data['joueurs']) {
              Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => Results(),
                  ));
            }
          }
          return Center(
            child: Text('VOUS AVEZ VOTE'),
          );
        },
      ),
    );
  }
4

2 回答 2

10

这是因为当您尝试导航到另一个屏幕时,Flutter 会触发框架构建,因此这是不可能的。

您可以安排后帧回调,以便在 Flutter 完成该小部件的树重建后立即导航。

import 'package:flutter/foundation.dart';

  WidgetsBinding.instance.addPostFrameCallback(
     (_) => Navigator.push(context,
       MaterialPageRoute(
         builder: (context) => Results(),
       ),
     ),
   );
于 2020-01-14T17:51:12.947 回答
1

如果导航是按钮按下时唯一发生的事情,我根本不会使用 Bloc,因为导航不是业务逻辑,应该由 UI 层完成。

如果您在按下按钮时有业务逻辑并且需要根据一些动态信息进行导航,那么我将在表示层(小部件)中再次进行导航以响应如下所示的成功状态。您还可以根据需要更改导航逻辑。

Widget loginButton(LoginBloc loginBloc) =>
      StreamBuilder<List<UserLoginResultElement>>(
          stream: loginBloc.loginStream,
          builder:
              (context, AsyncSnapshot<List<UserLoginResultElement>> snapshot) {
            print(snapshot.connectionState);
            Widget children;
            if (snapshot.hasError) {
              children = Padding(
                padding: const EdgeInsets.only(top: 16),
                child: Text('Error: ${snapshot.error}'),
              );
            } else {
              switch (snapshot.connectionState) {
                case ConnectionState.none:
                case ConnectionState.waiting:
                case ConnectionState.done:
                case ConnectionState.active:
                  children = BlockButtonWidget(
                    text: Text(
                      "LOGIN",
                      style: TextStyle(color: Theme.of(context).primaryColor),
                    ),
                    color: Theme.of(context).accentColor,
                    onPressed: () async {
                      try {
                        bloc.submit(_userNameController.value.text,
                            _passwordController.value.text, context);
                      } catch (ex) {
                        print(ex.toString());
                      }
                    },
                  );
                  break;
              }
            }
            if (snapshot.data != null && snapshot.hasData) {
              if (snapshot.data[0].code == "1") {

                SchedulerBinding.instance.addPostFrameCallback((_) {
                 Navigator.pushReplacementNamed(context, "/HomeScreen");
                });
              } else {
                print(Login Failed');
              }
            }
            return children;
          });
于 2020-11-04T10:32:39.050 回答