在执行 Widget 状态构建时导航
Posted
技术标签:
【中文标题】在执行 Widget 状态构建时导航【英文标题】:Navigate while Widget state build is being executed 【发布时间】:2019-12-05 15:26:28 【问题描述】:我正在构建一个简单的 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】:您不能在小部件树中直接调用Navigator
。如果您有event-state
builder,那么最好更改您正在呈现的小部件树:
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();
,
您必须在build
方法中返回Widget
。
或者,您也可以使用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
问题。
【讨论】:
但是我想离开启动屏幕并转到登录或主屏幕,而不是仅仅替换启动屏幕的内容。 啊,所以导航是在构建小部件之后发生的,这似乎是一个好方法。谢谢! 在后帧回调中返回进度小部件是没有用的,应该删除。这必须在 build() 方法中代替(并且不需要任何限定)。 @Ber 你是对的。感谢您的提醒,可能我直接复制粘贴了代码,无论如何它具有误导性。以上是关于在执行 Widget 状态构建时导航的主要内容,如果未能解决你的问题,请参考以下文章
Flutter 在 ListView 中不显示有状态的子 Widget