Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SchedulerBinding vs WidgetsBinding

Tags:

flutter

Actually I am working on Login page with Bloc. So when I press submit button, it does business logic on bloc then trying to navigate to home page based on the result. I tried this

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);
          },
        );
      },
    );
  }

But I got error like this The widget which was currently being built when the offending call was made....

Later then I found two solution: 1. Using SchedulerBinding, 2. Using WidgetsBinding. So what is the difference between SchedulerBinding and WidgetsBinding. Which one do I have to use?

Full Error Log:

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)
like image 388
Crazy Lazy Cat Avatar asked May 23 '19 10:05

Crazy Lazy Cat


People also ask

What is SchedulerBinding?

SchedulerBinding mixin Null safety. Scheduler for running the following: Transient callbacks, triggered by the system's dart:ui. PlatformDispatcher. onBeginFrame callback, for synchronizing the application's behavior to the system's display.

What is WidgetsFlutterBinding?

WidgetsFlutterBinding class Null safety. A concrete binding for applications based on the Widgets framework. This is the glue that binds the framework to the Flutter engine. When using the widgets framework, this binding, or one that implements the same interfaces, must be used.

What is the use of WidgetsBinding class?

addObserver and WidgetsBinding. removeObserver. This class can be extended directly, to get default behaviors for all of the handlers, or can used with the implements keyword, in which case all the handlers must be implemented (and the analyzer will list those that have been omitted).

What does WidgetsBinding instance addPostFrameCallback do?

addPostFrameCallback is run during a frame, just after the persistent frame callbacks (which is when the main rendering pipeline has been flushed). If a frame is in progress and post-frame callbacks haven't been executed yet, then the registered callback is still executed during the frame.


2 Answers

There are three callbacks available in flutter which rendering flutter widgets.

enter image description here

Transient callbacks: triggered by the system’s [Window.onBeginFrame] callback, for synchronizing the application’s behavior to the system’s display. For example, [Ticker]s and [AnimationController]s trigger from these.

Persistent callbacks: triggered by the system’s [Window.onDrawFrame] callback, for updating the system’s display after transient callbacks have executed. For example, the rendering layer uses this to drive its rendering pipeline.

Post-frame callbacks: which are run after persistent callbacks, just before returning from the [Window.onDrawFrame] callback. * Non-rendering tasks, to be run between frames. These are given a priority and are executed in priority order according to a schedulingStrategy. All above callbacks run sequentially, but for us, the last callback would work i.e Post-frame callbacks

Widgets Binding: The glue between the widgets layer and the Flutter engine. which comes with WidgetsBindingObserver mixin which has many callbacks but one which required to use is didChangeAppLifecycleState that returns AppLifecycleState.

Scheduler Binding: This is also similar to WidgetBinding but it does not provide any life cycle callbacks.

The below binding example would be called exactly the ones, means print statement like WidgetsBinding & SchedulerBinding will be printed only once as we called it initState(), but it will be called when build method finished it’s rendering.

void initState() {
  super.initState();
  print("initState");
  WidgetsBinding.instance.addPostFrameCallback((_) {
    print("WidgetsBinding");
  });
  SchedulerBinding.instance.addPostFrameCallback((_) {
    print("SchedulerBinding");
  });
}
like image 200
Jitesh Mohite Avatar answered Sep 24 '22 01:09

Jitesh Mohite


Both solutions do the same.

WidgetsBinding inherits this Method from SchedulerBinding https://api.flutter.dev/flutter/widgets/WidgetsBinding-mixin.html

It registers a callback that will be called after the frame is build. See in the docs: https://api.flutter.dev/flutter/scheduler/SchedulerBinding/addPostFrameCallback.html

like image 44
ZeRj Avatar answered Sep 24 '22 01:09

ZeRj