-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Explanation
Basically, when using Navigator.popUntil, where two associated Hero's are in the top most route and the one below it, where both get popped by the popUntil call, the State.dispose method will be called before the Hero inserts its child again, i.e. the route essentially gets popped "too fast" or the Hero is trying to insert into the tree when it should not.
Steps to reproduce
If you want to reproduce the error with the Gist, make sure to tap open and then push at least twice (and then popUntil to produce the exception).
-
Have two routes on the navigator stack with the same tag.
-
Have an
AnimatedBuilderas the child to theHerowidget in the lower route and pass aValueNotifieras theanimationparameter. -
Use
Navigator.popUntilto pop both of the routes at the same time.
Temporary fix
I had to come up with a workaround, extending ValueNotifier and overriding removeListener that checks if (disposed) return; before calling super.removeListener, where disposed is a bool that is set by overriding dispose, just to get rid of the error message.
If you want to understand my fix firsthand, you can just change the ValueNotifier in the Gist to a FixedValueNotifier.
Flutter logs
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown while finalizing the widget tree:
A ValueNotifier<dynamic> was used after being disposed.
Once you have called dispose() on a ValueNotifier<dynamic>, it can no longer be used.
When the exception was thrown, this was the stack:
#0 ChangeNotifier._debugAssertNotDisposed.<anonymous closure> (package:flutter/src/foundation/change_notifier.dart:105:9)
#1 ChangeNotifier._debugAssertNotDisposed (package:flutter/src/foundation/change_notifier.dart:111:6)
#2 ChangeNotifier.removeListener (package:flutter/src/foundation/change_notifier.dart:166:12)
#3 _AnimatedState.dispose (package:flutter/src/widgets/transitions.dart:137:23)
#4 StatefulElement.unmount (package:flutter/src/widgets/framework.dart:4107:12)
...
Flutter doctor
Flutter: v1.7.12-pre.40
Further notes
Please correct me if my assumption about the Hero inserting at a wrong point in time is wrong here. I feel like I understood the gist of the problem given that my reproducible example is concise and I found a working fix. In that regard everything works as I would it expect it to now, just that this behavior is unwanted (I believe).
It took me many attempts over different Flutter versions to figure this out. I believe that it would be very helpful if the exception message could somehow point to user written code if that is possible.