Skip to content

Hero inserts widgets After Dispose #35555

@creativecreatorormaybenot

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

https://gist.github.com/creativecreatorormaybenot/505fb58446e41fac140c459039d7029a

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).

  1. Have two routes on the navigator stack with the same tag.

  2. Have an AnimatedBuilder as the child to the Hero widget in the lower route and pass a ValueNotifier as the animation parameter.

  3. Use Navigator.popUntil to 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    a: animationAnimation APIsf: routesNavigator, Router, and related APIs.found in release: 1.20Found to occur in 1.20frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer version

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions