在执行小部件状态构建时进行导航

时间:2019-07-27 17:07:16

标签: flutter flutter-navigation flutter-provider

我正在构建一个简单的Flutter应用。它的启动屏幕确定用户是否已登录,并根据该信息随后重定向到登录屏幕或主/主屏幕。

我的启动屏幕是StatefulWidget,其状态如下所示。它使用扩展了ChangeNotifier的ViewModel类(它的代码是无关紧要的,因此我没有包括它)。

class _LaunchPageState extends State<LaunchPage> {
          LaunchViewModel _viewModel = LaunchViewModel();

          @override
          void initState() {
            super.initState();
            _viewModel.checkSessionStatus();
          }

          @override
          Widget build(BuildContext context) {
            return ChangeNotifierProvider<LaunchViewModel>(
              builder: (_) => _viewModel,
              child: Scaffold(
                body: Consumer<LaunchViewModel>(
                  builder: (context, viewModel, _) {
                    if (viewModel.state is LaunchInitial) {
                      return CircularProgressIndicator();
                    }
                    if (viewModel.state is LaunchLoginPage) {
                      Navigator.pushNamed(context, "login");
                    }
                    if (viewModel.state is LaunchMainPage) {
                      Navigator.pushNamed(context, "main");
                    }
                    return Container();
                  },
                ),
              ),
            );
          }
        }

ViewModel发出3种状态之一:

  • LaunchInitial:默认状态。
  • LaunchLoginPage:指示应显示登录页面。
  • LaunchMainPage:指示应显示主页。

可以很好地处理LaunchInitial状态,并在屏幕上显示进度条。但是其他2种状态会导致应用崩溃。引发以下错误:

This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets

似乎在执行消费者的build方法时尝试重定向到另一个屏幕导致了此问题。正确的方法是什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

您无法在小部件树中直接调用Navigator。如果您拥有event-state构建器,那么最好更改要渲染的窗口小部件树:

builder: (context, viewModel, _) {
                    if (viewModel.state is LaunchInitial) {
                      return CircularProgressIndicator();
                    }
                    if (viewModel.state is LaunchLoginPage) {
                      return LoginPage();
                    }
                    if (viewModel.state is LaunchMainPage) {
                      return MainPage();
                    }
                    return Container();
                  },

您必须使用Widget方法中的每个孩子返回build

或者,您也可以使用Navigation

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (viewModel.state is LaunchInitial) {
        return CircularProgressIndicator();
      }
      if (viewModel.state is LaunchLoginPage) {
        Navigator.pushNamed(context, "login");
      }
      if (viewModel.state is LaunchMainPage) {
        Navigator.pushNamed(context, "main");
      }
      return Container();
    });
    super.initState();
  }

addPostFrameCallback方法将被称为正确完成build方法的答案,您可以在其中导航。