编辑:问题完全按照我想要的在新问题主题中解决:
小部件树中的条件导航
旧问题:
这是我的启动屏幕,我想创建条件导航,但是据我了解,FutureBuilder没有导航逻辑。
这是我的启动屏幕构建方法:
@override Widget build(BuildContext context) { return Material( child: ScopedModelDescendant<MainModel>( builder: (BuildContext context, Widget child, MainModel model) { return FutureBuilder( future: model.bootUp(), builder: (context, bootSnapshot) { print('====${bootSnapshot.data} is SNAPSHOT DATA===='); return !bootSnapshot.hasData ? _buildSplash(context) : bootSnapshot.data ? FutureBuilder( future: model.fetchAll(model.tempUser), builder: (context, dataSnapshot) { return !dataSnapshot.hasData ? _buildSplash(context) : Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => HomePage()), ); }) : Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => FirstScreen(), ), ); }, ); }, ), ); }
如您在代码中所见,首先我检查用户登录之前是否使用异步方法,然后如果他之前登录,那么我正在获取与他相关的数据,一旦获取完成,我想导航到用户主页。
错误日志:
I/flutter (24348): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ I/flutter (24348): The following assertion was thrown building FutureBuilder<String>(dirty, state: I/flutter (24348): _FutureBuilderState<String>#e0594): I/flutter (24348): setState() or markNeedsBuild() called during build. I/flutter (24348): This Overlay widget cannot be marked as needing to build because the framework is already in the I/flutter (24348): process of building widgets. A widget can be marked as needing to be built during the build phase I/flutter (24348): only if one of its ancestors is currently building. This exception is allowed because the framework I/flutter (24348): builds parent widgets before children, which means a dirty descendant will always be built. I/flutter (24348): Otherwise, the framework might not visit this widget during this build phase. I/flutter (24348): The widget on which setState() or markNeedsBuild() was called was: I/flutter (24348): Overlay-[LabeledGlobalKey<OverlayState>#c7eb6](state: OverlayState#953bd(entries: I/flutter (24348): [OverlayEntry#b9486(opaque: false; maintainState: false), OverlayEntry#af059(opaque: false; I/flutter (24348): maintainState: true), OverlayEntry#81d00(opaque: false; maintainState: false), I/flutter (24348): OverlayEntry#be7c4(opaque: false; maintainState: true)])) I/flutter (24348): The widget which was currently being built when the offending call was made was: I/flutter (24348): FutureBuilder<String>(dirty, state: _FutureBuilderState<String>#e0594) I/flutter (24348): I/flutter (24348): When the exception was thrown, this was the stack: I/flutter (24348): #0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3485:11) I/flutter (24348): #1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3511:6) I/flutter (24348): #2 State.setState (package:flutter/src/widgets/framework.dart:1146:14) I/flutter (24348): #3 OverlayState.insertAll (package:flutter/src/widgets/overlay.dart:301:5) I/flutter (24348): #4 OverlayRoute.install (package:flutter/src/widgets/routes.dart:43:24) I/flutter (24348): #5 TransitionRoute.install (package:flutter/src/widgets/routes.dart:185:11) I/flutter (24348): #6 ModalRoute.install (package:flutter/src/widgets/routes.dart:861:11) I/flutter (24348): #7 NavigatorState.pushReplacement (package:flutter/src/widgets/navigator.dart:1618:14) I/flutter (24348): #8 BootScreen.build.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:mostadam/pages/boot_screen.dart:49:49) I/flutter (24348): #9 _FutureBuilderState.build (package:flutter/src/widgets/async.dart) I/flutter (24348): #10 StatefulElement.build (package:flutter/src/widgets/framework.dart:3809:27) I/flutter (24348): #11 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15) I/flutter (24348): #12 Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5) I/flutter (24348): #13 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2286:33) I/flutter (24348): #14 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:676:20) I/flutter (24348): #15 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5) I/flutter (24348): #16 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15) I/flutter (24348): #17 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9) I/flutter (24348): #18 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5) I/flutter (24348): #19 _invoke (dart:ui/hooks.dart:154:13) I/flutter (24348): #20 _drawFrame (dart:ui/hooks.dart:143:3)
Anmol已回答了评论的问题。
解决方案很简单,只需返回要导航的页面即可。但是对于某些罕见的特殊情况,IMO还远远不够。我希望我们有更好的选择来进行将来的更新。
解:
代替
Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => HomePage();
简单的说:
return HomePage();
相同于:
return FirstScreen();