【问题标题】:Flutter: navigate to another screen from inside of StreamBuilder builder callbackFlutter:从 StreamBuilder 构建器回调内部导航到另一个屏幕
【发布时间】: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) 将导航安排到事件队列的末尾,但这很糟糕。这里有适当的解决方案吗?

【问题讨论】:

    标签: flutter stream-builder


    【解决方案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... );
       }
    

    【讨论】:

      猜你喜欢
      • 2020-03-06
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      • 2010-11-09
      • 1970-01-01
      • 2021-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多