flutter SchedulerBinding与WidgetsBinding

x7rlezfr  于 2023-03-24  发布在  Flutter
关注(0)|答案(2)|浏览(234)

实际上我正在用Bloc进行登录页面。所以当我按下提交按钮时,它会在Bloc上执行业务逻辑,然后根据结果导航到主页。我试过这个

Widget submitButton() {
    return StreamBuilder(
      stream: bloc.submitStream,
      builder: (context, snapshot) {
        if (snapshot.data == "Success") {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => RegisterPage(),
            ),
          );
        }
        return RaisedButton(
          child: Text("Submit"),
          onPressed: () {
            bloc.submitSink.add(null);
          },
        );
      },
    );
  }

但是我得到了类似The widget which was currently being built when the offending call was made...的错误。
后来我找到了两个解决办法:1. Using SchedulerBinding,2. Using WidgetsBinding。那么SchedulerBinding和WidgetsBinding有什么区别呢?我应该使用哪一个?

  • 完整错误日志:*
I/flutter (17893): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (17893): The following assertion was thrown building LayoutBuilder:
I/flutter (17893): setState() or markNeedsBuild() called during build.
I/flutter (17893): This Overlay widget cannot be marked as needing to build because the framework is already in the
I/flutter (17893): process of building widgets. A widget can be marked as needing to be built during the build phase
I/flutter (17893): only if one of its ancestors is currently building. This exception is allowed because the framework
I/flutter (17893): builds parent widgets before children, which means a dirty descendant will always be built.
I/flutter (17893): Otherwise, the framework might not visit this widget during this build phase.
I/flutter (17893): The widget on which setState() or markNeedsBuild() was called was:
I/flutter (17893):   Overlay-[LabeledGlobalKey<OverlayState>#70089](state: OverlayState#3bf13(entries:
I/flutter (17893):   [OverlayEntry#9280a(opaque: false; maintainState: false), OverlayEntry#1af87(opaque: false;
I/flutter (17893):   maintainState: true), OverlayEntry#9fb49(opaque: false; maintainState: false),
I/flutter (17893):   OverlayEntry#87589(opaque: false; maintainState: true)]))
I/flutter (17893): The widget which was currently being built when the offending call was made was:
I/flutter (17893):   LayoutBuilder(renderObject: _RenderLayoutBuilder#d3baf relayoutBoundary=up1 NEEDS-LAYOUT
I/flutter (17893):   NEEDS-PAINT)
I/flutter (17893): 
I/flutter (17893): When the exception was thrown, this was the stack:
I/flutter (17893): #0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3497:11)
I/flutter (17893): #1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3523:6)
I/flutter (17893): #2      State.setState (package:flutter/src/widgets/framework.dart:1138:14)
I/flutter (17893): #3      OverlayState.insertAll (package:flutter/src/widgets/overlay.dart:301:5)
I/flutter (17893): #4      OverlayRoute.install (package:flutter/src/widgets/routes.dart:43:24)
I/flutter (17893): #5      TransitionRoute.install (package:flutter/src/widgets/routes.dart:184:11)
I/flutter (17893): #6      ModalRoute.install (package:flutter/src/widgets/routes.dart:899:11)
I/flutter (17893): #7      NavigatorState.push (package:flutter/src/widgets/navigator.dart:1672:11)
I/flutter (17893): #8      Navigator.push (package:flutter/src/widgets/navigator.dart:1011:34)
I/flutter (17893): #9      _SetPinPageState.submitButton (package:technicalreport/screens/set_pin_page.dart:94:15)
I/flutter (17893): #10     _SetPinPageState.build.<anonymous closure>.<anonymous closure> (package:technicalreport/screens/set_pin_page.dart:52:29)
I/flutter (17893): #11     OrientationBuilder._buildWithConstraints (package:flutter/src/widgets/orientation_builder.dart:48:12)
I/flutter (17893): #12     _LayoutBuilderElement._layout.<anonymous closure> (package:flutter/src/widgets/layout_builder.dart:111:26)
I/flutter (17893): #13     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2253:19)
I/flutter (17893): #14     _LayoutBuilderElement._layout (package:flutter/src/widgets/layout_builder.dart:107:11)
I/flutter (17893): #15     RenderObject.invokeLayoutCallback.<anonymous closure> (package:flutter/src/rendering/object.dart:1728:58)
I/flutter (17893): #16     PipelineOwner._enableMutationsToDirtySubtrees (package:flutter/src/rendering/object.dart:797:15)
I/flutter (17893): #17     RenderObject.invokeLayoutCallback (package:flutter/src/rendering/object.dart:1728:13)
I/flutter (17893): #18     _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:205:5)
I/flutter (17893): #19     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #20     MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:142:11)
I/flutter (17893): #21     _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:350:7)
I/flutter (17893): #22     MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:212:7)
I/flutter (17893): #23     RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:356:14)
I/flutter (17893): #24     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #25     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #26     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #27     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #28     _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1206:11)
I/flutter (17893): #29     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #30     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #31     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #32     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #33     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #34     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #35     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #36     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #37     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #38     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #39     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #40     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #41     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #42     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #43     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #44     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #45     RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3032:13)
I/flutter (17893): #46     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #47     RenderStack.performLayout (package:flutter/src/rendering/stack.dart:510:15)
I/flutter (17893): #48     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #49     __RenderTheatre&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #50     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #51     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #52     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #53     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #54     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #55     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #56     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #57     _RenderProxyBox&RenderBox&RenderObjectWithChildMixin&RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:105:13)
I/flutter (17893): #58     RenderObject.layout (package:flutter/src/rendering/object.dart:1632:7)
I/flutter (17893): #59     RenderView.performLayout (package:flutter/src/rendering/view.dart:151:13)
I/flutter (17893): #60     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1507:7)
I/flutter (17893): #61     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:766:18)
I/flutter (17893): #62     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:329:19)
I/flutter (17893): #63     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:701:13)
I/flutter (17893): #64     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:268:5)
I/flutter (17893): #65     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:988:15)
I/flutter (17893): #66     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:928:9)
I/flutter (17893): #67     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:749:7)
I/flutter (17893): #76     _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19)
I/flutter (17893): #77     _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5)
I/flutter (17893): #78     _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
I/flutter (17893): (elided 8 frames from package dart:async)
I/flutter (17893): ════════════════════════════════════════════════════════════════════════════════════════════════════
D/        (17893): HostConnection::get() New Host Connection established 0xa0ba6b40, tid 17931
D/EGL_emulation(17893): eglMakeCurrent: 0xa3508c40: ver 2 0 (tinfo 0x9084ab40)
68bkxrlz

68bkxrlz1#

flutter中有三个可用的回调函数,用于渲染flutter小部件。

https://api.flutter.dev/flutter/scheduler/SchedulerBinding-mixin.html处的文档所述-

** transient 回调:**由系统的[Window.onBeginFrame]回调触发,用于将应用的行为同步到系统的显示。例如[Ticker]s和[AnimationController]s就是从这些触发的。
**持久回调:**由系统的[Window.onDrawFrame]回调触发,用于在执行了 transient 回调后更新系统的显示,例如渲染层使用此来驱动其渲染管道。
**帧后回调:**在[Window.onDrawFrame]回调返回之前,在持久回调之后运行。

非渲染任务,在帧之间运行。这些任务被赋予优先级,并根据schedulingStrategy的优先级顺序执行。
以上所有回调都是按顺序运行的,但对我们来说,最后一个回调也可以工作,即帧后回调

**Widgets Binding:**widgets层和Flutter引擎之间的粘合剂。它自带WidgetsBindingObserver mixin,mixin有很多回调,但需要使用的是返回AppLifecycleState的didChangeAppLifecycleState
**Scheduler Binding:**与WidgetBinding类似,但不提供任何生命周期回调。

下面的绑定示例将被称为完全相同的,这意味着像WidgetsBinding & SchedulerBinding这样的print语句将只打印一次,因为我们称之为initState(),但它将在构建方法完成渲染时被调用。

void initState() {
  super.initState();
  print("initState");
  WidgetsBinding.instance.addPostFrameCallback((_) {
    print("WidgetsBinding");
  });
  SchedulerBinding.instance.addPostFrameCallback((_) {
    print("SchedulerBinding");
  });
}
9avjhtql

9avjhtql2#

这两种解决方案的作用相同。
小部件绑定从调度程序绑定https://api.flutter.dev/flutter/widgets/WidgetsBinding-mixin.html继承此方法
它注册了一个回调函数,该函数将在框架构建完成后调用。请参阅文档:https://api.flutter.dev/flutter/scheduler/SchedulerBinding/addPostFrameCallback.html

相关问题