Flutter:从 StreamBuilder 构建器回调内部导航到另一个屏幕
Posted
技术标签:
【中文标题】Flutter:从 StreamBuilder 构建器回调内部导航到另一个屏幕【英文标题】:Flutter: navigate to another screen from inside of StreamBuilder builder callback 【发布时间】:2019-09-30 16:11:54 【问题描述】:我有一个初始屏幕和一个StreamBuilder
,它发出一个包含身份验证状态信息的状态。当身份验证状态已知时,我想导航到登录页面或主页。但是当我写像Navigator.of(context).pushReplacement(...)
这样的东西时,我得到了
I/flutter (2058): ══╡ 小部件库发现异常╞════════════════════════════════════ ════════════════════════════ I/flutter(2058):在构建 StreamBuilder(脏,状态: 我/颤振(2058):_StreamBuilderBaseState>#f4346): I/flutter (2058):在构建期间调用 setState() 或 markNeedsBuild()。 I/flutter (2058):这个 Overlay 小部件不能被标记为需要构建,因为框架已经在 I/flutter (2058):构建小部件的过程。可以在构建阶段将小部件标记为需要构建 I/flutter (2058):仅当其祖先之一当前正在构建时。这个例外是允许的,因为框架 I/flutter (2058):在子组件之前构建父组件,这意味着将始终构建脏后代。 I/flutter (2058):否则,框架可能不会在此构建阶段访问此小部件。 I/flutter (2058):调用 setState() 或 markNeedsBuild() 的小部件是: 我/颤振(2058):覆盖-[LabeledGlobalKey#e0460](状态:OverlayState#ab1a5(条目: 我/颤振(2058):[OverlayEntry#4e962(不透明:假;维护状态:假),OverlayEntry#7656a(不透明:假; I/flutter(2058):maintainState:true),OverlayEntry#1f86e(不透明:false;maintainState:false), 我/颤振(2058):OverlayEntry#05a15(不透明:假;维护状态:真)])) I/flutter ( 2058): 发出违规调用时当前正在构建的小部件是: 我/颤振(2058):StreamBuilder(脏,状态:_StreamBuilderBaseState>#f4346) 我/颤动(2058): I/flutter (2058):当异常被抛出时,这是堆栈: 我/颤振(2058):#0 Element.markNeedsBuild。 (包:flutter/src/widgets/framework.dart:3503:11) I/flutter (2058): #1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3529:6) I/flutter (2058): #2 State.setState (package:flutter/src/widgets/framework.dart:1133:14) I/flutter (2058): #3 OverlayState.insertAll (package:flutter/src/widgets/overlay.dart:346:5) I/flutter (2058): #4 OverlayRoute.install (package:flutter/src/widgets/routes.dart:43:24) I/flutter (2058): #5 TransitionRoute.install (package:flutter/src/widgets/routes.dart:180:11) I/flutter (2058): #6 ModalRoute.install (package:flutter/src/widgets/routes.dart:895:11) I/flutter (2058): #7 NavigatorState.pushReplacement (package:flutter/src/widgets/navigator.dart:1799:14) I/flutter (2058): #8 _replace (package:map_chat/application/navigation.dart:75:27) I/flutter (2058): #9 _SignInPage.replace (package:map_chat/application/navigation.dart:67:5) I/flutter (2058): #10 Roadmap.replace (package:map_chat/application/navigation.dart:25:18) 我/颤振(2058):#11 _SplashPageState._buildPageBasedOnAuthenticationState(包:map_chat/feature/splash.dart:52:19) 我/颤振(2058):#12 _SplashPageState._buildSplashScreen(包:map_chat/feature/splash.dart:40:11) 我/颤振(2058):#13 _SplashPageState._buildPage。 (包:map_chat/feature/splash.dart:27:18) I/flutter(2058):#14 StreamBuilder.build(包:flutter/src/widgets/async.dart:425:74) I/flutter(2058):#15 _StreamBuilderBaseState.build(包:flutter/src/widgets/async.dart:125:48) I/flutter (2058): #16 StatefulElement.build (package:flutter/src/widgets/framework.dart:3825:27) I/flutter (2058): #17 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3739:15) I/flutter (2058): #18 Element.rebuild (package:flutter/src/widgets/framework.dart:3565:5) I/flutter (2058): #19 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2278:33) I/flutter (2058): #20 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:700:20) I/flutter (2058): #21 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:286:5) I/flutter (2058): #22 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1012:15) I/flutter (2058): #23 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:952:9) I/flutter (2058):#24 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame。 (包:flutter/src/scheduler/binding.dart:773:7) I/flutter (2058):#33 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:382:19) I/flutter (2058):#34 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5) I/flutter (2058):#35 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:171:12) I/flutter(2058):(从包 dart:async 和包 dart:async-patch 中删除了 8 帧)
我发现的唯一解决方法是使用Future(...).then(navigate)
将导航安排到事件队列的末尾,但这很糟糕。这里有适当的解决方案吗?
【问题讨论】:
【参考方案1】:您可以在构建方法之外收听您的流并从那里重定向到另一个视图。
----已编辑----
这是您如何做到这一点的示例:
@override
void initState()
super.initState();
Future.delayed(Duration.zero, _verify);
void _verify()
final _myBloc = BlocProvider.getBloc<MyBloc>();
_myBloc.myStream.listen((data)
// Redirect to another view, given your condition
if (data)
Navigator.of(context).pushNamed("my-new-route");
);
记得保存listen
方法返回的StreamSubscription
对象,这样就可以取消dispose()
上的订阅了。
【讨论】:
是的,这对我来说当然更有意义。刚刚发现我可以在Consumer
小部件中创建一个流订阅并在适当的时间处理它
你的回答不完整,最好能举个例子!【参考方案2】:
我仍然对我的解决方案不满意,但我使用了
if(snapshot.hasdata && snapshot.data.navigate)
Future.microtask(() => Navigator.of(context).push... );
【讨论】:
以上是关于Flutter:从 StreamBuilder 构建器回调内部导航到另一个屏幕的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:从 StreamBuilder 构建器回调内部导航到另一个屏幕
从 mysql 获取数据到 StreamBuilder Flutter