flutter_easy_refresh icon indicating copy to clipboard operation
flutter_easy_refresh copied to clipboard

setState() or markNeedsBuild() called during build

Open Pwuts opened this issue 3 years ago • 10 comments

The following assertion was thrown while dispatching notifications for HeaderNotifier:
setState() or markNeedsBuild() called during build.

This ValueListenableBuilder<IndicatorState?> widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: ValueListenableBuilder<IndicatorState?>
    state: _ValueListenableBuilderState<IndicatorState?>#395da
The widget which was currently being built when the offending call was made was: _BodyBuilder
When the exception was thrown, this was the stack
#0      Element.markNeedsBuild.<anonymous closure>      package:flutter/…/widgets/framework.dart:4476
#1      Element.markNeedsBuild                          package:flutter/…/widgets/framework.dart:4491
#2      State.setState                                  package:flutter/…/widgets/framework.dart:1129
#3      _ValueListenableBuilderState._valueChanged      package:flutter/…/widgets/value_listenable_builder.dart:182
#4      IndicatorStateListenable._onNotify              package:easy_refresh/…/indicator/indicator.dart:232
#5      ChangeNotifier.notifyListeners                  package:flutter/…/foundation/change_notifier.dart:324
#6      IndicatorNotifier._update                       package:easy_refresh/…/notifier/indicator_notifier.dart:375
#7      _EasyRefreshState.didUpdateWidget               package:easy_refresh/src/easy_refresh.dart:310
#8      StatefulElement.update                          package:flutter/…/widgets/framework.dart:4992

When the widget tree is rebuilt for whatever reason, and the _EasyRefreshState is associated to a new widget, didUpdateWidget is called which ends up triggering _ValueListenableBuilderState._valueChanged, scheduling another rebuild, causing this error.

I'm not sure, but this might be solved by being more selective in calling notifyListeners() on indicator_notifier.dart:375. E.g. call it when the state changes, but not when _headerNotifier._update() is called to attach a new widget.

Possibly related: #579

I can ignore this error and the app will work fine, but during debugging this constantly triggers my debug tools.

Pwuts avatar Aug 18 '22 15:08 Pwuts

Can you provide a complete reproducible code example?

xuelongqy avatar Feb 01 '23 09:02 xuelongqy

Future.delayed(Duration.zero, () async { myFunction(); });

This can be solved

zebraoo avatar Feb 24 '23 02:02 zebraoo

I have the same issue. Did you able to find a solution?

fikretsengul avatar Jan 15 '24 18:01 fikretsengul

I have the same issue. Did you able to find a solution?

Can you provide a reproduction case?

xuelongqy avatar Jan 16 '24 02:01 xuelongqy

@xuelongqy You can checkout my fork of super_cupertino_navigation_bar library where I implemented pull to refresh to mimic iOS refresher. (In the nested scroll example of the app, you can pull to refresh and check the debug console when you hot reload the app with any change)

https://github.com/fikretsengul/super_cupertino_navigation_bar/tree/dev

I used the listener pattern of easy_refresh library. But when the widget tree is rebuilt for whatever reason (like changing a text which leads a hot reload), and the _EasyRefreshState is associated to a new widget, didUpdateWidget is called which ends up triggering _ValueListenableBuilderState._valueChanged, scheduling another rebuild, causing this error.

Screenshot 2024-01-19 at 13 24 09

Like @Pwuts said, we can ignore this error and the app will work fine, but during debugging this constantly throws exception to the debug console.

fikretsengul avatar Jan 19 '24 10:01 fikretsengul

@xuelongqy Sorry to bother you again, but when will there be an update on this?

fikretsengul avatar Jan 24 '24 22:01 fikretsengul

@xuelongqy Sorry to bother you again, but when will there be an update on this?

Can you give me a reproducible case?

xuelongqy avatar Jan 25 '24 04:01 xuelongqy

You can checkout latest test version of my boilerplate on test branch to check this error out:

https://github.com/fikretsengul/flutter_advanced_boilerplate/tree/test

Commands to run in order to run app: (You should use fvm, or remove "sdkPath: .fvm/flutter_sdk" line from melos.yaml)

fvm use 3.16.5 fvm flutter pub get melos bs (This will run fvm flutter run on every package and also build_runner)

Then run the app from app/main.dart. Don't forget to do a hot reload to see the error.

fikretsengul avatar Jan 25 '24 23:01 fikretsengul

You can checkout latest test version of my boilerplate on test branch to check this error out:

https://github.com/fikretsengul/flutter_advanced_boilerplate/tree/test

Commands to run in order to run app: (You should use fvm, or remove "sdkPath: .fvm/flutter_sdk" line from melos.yaml)

fvm use 3.16.5 fvm flutter pub get melos bs (This will run fvm flutter run on every package and also build_runner)

Then run the app from app/main.dart. Don't forget to do a hot reload to see the error.

I don't have a macOS device at the moment and I'm just doing a tentative fix. You can use the latest code from the v3 branch for testing.

xuelongqy avatar Jan 26 '24 03:01 xuelongqy

@xuelongqy Thank you, I can confirm that it's working smoothly now. Thank you very much for your fast response, interest and for this wonderful library.

fikretsengul avatar Jan 26 '24 10:01 fikretsengul

Fixed in 3.3.5

xuelongqy avatar Apr 19 '24 06:04 xuelongqy