在执行 Widget 状态构建时导航

Navigate while Widget state build is being executed

我正在构建一个简单的 Flutter 应用程序。它的启动屏幕确定用户是否登录,并根据该情况重定向到登录或之后的 main/home 屏幕。

我的启动屏幕是 StatefulWidget,其状态如下所示。它使用扩展 ChangeNotifier 的 ViewModel class(它的代码不相关,所以我没有包含它)。

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 状态处理良好,屏幕上显示进度条。但其他 2 个状态导致应用程序崩溃。抛出以下错误:

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

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

谢谢!

您不能在小部件树中直接调用 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();
                  },

你必须 return Widgetbuild 方法中的每个 child。

或者,您可以使用 Navigation:

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

addPostFrameCallback 方法将在 build 方法完成后立即调用,您可以在其中导航。

确保您的 provider 没有 lifecycle 问题。