5

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

我的启动屏幕是一个StatefulWidget,它的状态如下图所示。它使用扩展的 ViewModel 类ChangeNotifier(它的代码无关紧要,所以我没有包含它)。

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 发出以下三种状态之一:

  • 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执行消费者方法时尝试重定向到另一个屏幕会导致此问题。这样做的正确方法是什么?

谢谢!

4

1 回答 1

6

您不能直接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 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问题。

于 2019-07-27T18:04:37.220 回答