Flutter如何无需onPressed等触发,在state变量变更时实现页面跳转
报错原因
你遇到的报错本质是在组件build的同步执行流程里触发了新的页面压栈操作,Navigator.push本质会修改Overlay的状态,相当于在组件还没完成当前构建的时候就要求框架重新构建其他组件,违反了Flutter的构建流程约束。
解决方案
针对你使用StoreConnector的Redux场景,推荐以下两种可行方案:
方案1:使用addPostFrameCallback延迟执行跳转
该回调会在当前帧所有组件构建完成之后才执行,完全不会干扰当前的build流程:
Widget build(BuildContext context) { return StoreConnector<AppState, AppState>( converter: (store) => store.state, builder: (context, state) { // 先判断你要监听的指定变量是否符合跳转条件 if (state.你要监听的状态变量 == 触发跳转的目标值) { WidgetsBinding.instance.addPostFrameCallback((_) { Navigator.push( context, MaterialPageRoute(builder: (context) => const SomeScreen()), ); // 跳转后建议dispatch一个action重置状态标记,避免重复触发跳转 // store.dispatch(ResetJumpFlagAction()); }); } // 此处正常返回Launcher页面的渲染组件即可 return const Scaffold( body: Center(child: Text('Launcher页面')), ); }, ); }
方案2:使用StoreConnector自带的onDidChange回调(更推荐)
StoreConnector本身提供了独立于build流程的状态变化监听回调,只有状态真的发生变化时才会触发,不需要每次build都做判断:
Widget build(BuildContext context) { return StoreConnector<AppState, AppState>( converter: (store) => store.state, // 状态变化时触发该回调,不会干涉build流程 onDidChange: (previousState, currentState) { // 判断目标变量是否发生符合要求的变化,避免重复触发 if (previousState?.你要监听的状态变量 != 目标值 && currentState.你要监听的状态变量 == 目标值) { Navigator.push( context, MaterialPageRoute(builder: (context) => const SomeScreen()), ); // 同样可以在这里重置状态标记 // store.dispatch(ResetJumpFlagAction()); } }, builder: (context, state) { // builder内只负责页面渲染,不要放跳转逻辑 return const Scaffold( body: Center(child: Text('Launcher页面')), ); }, ); }
注意事项
- 一定要加跳转条件和状态重置逻辑,避免页面被重复压入栈多次
- 如果跳转后Launcher页面不需要再保留在栈中,可以把
Navigator.push替换为Navigator.pushReplacement
内容的提问来源于stack exchange,提问作者thunermay
相关产品推荐
相关产品推荐

