Do not wait until dispose before removing replaced/popped page#182315
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
There was a problem hiding this comment.
Code Review
This pull request addresses a regression that caused a flicker effect when popping or replacing a nested route. The issue stemmed from onDidRemovePage being called too late in the _RouteLifecycle.dispose phase. The fix correctly moves the onDidRemovePage call to happen immediately within handlePop and handlePush (for replacements), ensuring the navigator's page list is updated promptly and preventing the outdated page from being rebuilt. The changes look correct and effectively resolve the described problem. I've added one suggestion to refactor the newly added code blocks into a helper method to reduce duplication and improve maintainability.
| if (previousPresent != null && previousPresent._isPageBased) { | ||
| final page = previousPresent.settings as Page<Object?>; | ||
| navigator.widget.onDidRemovePage?.call(page); | ||
| } |
There was a problem hiding this comment.
This logic is very similar to the code added in _RouteEntry.handlePop (lines 3332-3335). To improve maintainability and avoid duplication, consider extracting this into a shared private helper method within _RouteEntry.
For example:
void _didRemovePage(NavigatorState navigator, Route<dynamic> removedRoute) {
assert(removedRoute._isPageBased);
final page = removedRoute.settings as Page<Object?>;
navigator.widget.onDidRemovePage?.call(page);
}You could then call this helper from both handlePush and handlePop.
justinmc
left a comment
There was a problem hiding this comment.
The approach looks good. Are you sure that replace and pop are the only two things that can result in needing to call onDidRemovePage?
| if (previousPresent != null && previousPresent._isPageBased) { | ||
| final page = previousPresent.settings as Page<Object?>; | ||
| navigator.widget.onDidRemovePage?.call(page); | ||
| } |
Maybe |
justinmc
left a comment
There was a problem hiding this comment.
LGTM 👍 . Heads up there's an analyzer failure.
Maybe
removeRoute, but calling that method means the user already has therouteto be removed, so they can just callonDidRemovePage(route.settings)directly I think?
Sounds good as long as the tests pass.
…11060) Manual roll requested by tarrinneal@google.com flutter/flutter@6e4a481...c023e5b 2026-02-18 zhongliu88889@gmail.com [web] Pass form validation errors to screen readers via aria-description (flutter/flutter#180556) 2026-02-18 engine-flutter-autoroll@skia.org Roll Packages from f83926f to 59f905c (10 revisions) (flutter/flutter#182547) 2026-02-18 104147021+MohammedTarigg@users.noreply.github.com flutter_tools: Copy vendored frameworks from plugin podspecs in ios/macos-framework builds (flutter/flutter#180135) 2026-02-18 fluttergithubbot@gmail.com Marks Windows framework_tests_misc_leak_tracking to be unflaky (flutter/flutter#182534) 2026-02-18 brackenavaron@gmail.com Allow TabBar to receive a TabBarScrollController (flutter/flutter#180389) 2026-02-18 brackenavaron@gmail.com Clean up cross imports in single_child_scroll_view_test.dart, decorated_sliver_test.dart, draggable_scrollable_sheet_test.dart (flutter/flutter#181613) 2026-02-18 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from mcN42vw48OPH3JDNm... to Ihau0pUz3u5ajw42u... (flutter/flutter#182530) 2026-02-18 scheglov@google.com Analyzer, require 10.1.0, fix deprecations in dependency_graph.dart (flutter/flutter#182507) 2026-02-17 34465683+rkishan516@users.noreply.github.com Refactor: Remove material from actions test (flutter/flutter#181702) 2026-02-17 jhy03261997@gmail.com [a11y] RangeSlider mouse interaction should change keyboard focus (flutter/flutter#182185) 2026-02-17 116356835+AbdeMohlbi@users.noreply.github.com Remove more getters from userMessages class (flutter/flutter#182166) 2026-02-17 evanwall@buffalo.edu Implement getUniformMatX and getUniformMatXArray functionality on web (flutter/flutter#182249) 2026-02-17 victorsanniay@gmail.com Do not wait until dispose before removing replaced/popped page (flutter/flutter#182315) 2026-02-17 iliyazelenkog@gmail.com Add contentTextStyle support to SimpleDialog (flutter/flutter#178824) 2026-02-17 alex.medinsh@gmail.com Filter error messages from `emulator -list-avds` output (flutter/flutter#180802) 2026-02-17 brackenavaron@gmail.com [Reland] Cupertino cross imports (flutter/flutter#182416) 2026-02-17 engine-flutter-autoroll@skia.org Roll Packages from 09104b0 to f83926f (1 revision) (flutter/flutter#182504) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC stuartmorgan@google.com,tarrinneal@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…er#182315) Regression was introduced in [Cleans up navigator pop and remove logic](https://github.com/flutter/flutter/pull/175612/changes#top). That PR moved the `onDidRemovePage` call to `_flushHistoryUpdates` in phase `_RouteLifecycle.dispose`. But waiting until `dispose` causes potential problems if the widget is rebuilt in a phase preceding that (but after `pop` or `pushReplacement` has been called). So the outdated page remains in the pages list even after it has been marked for removal. This is causing the page to be pushed again before it is finally removed, causing the flicker. ## Before https://github.com/user-attachments/assets/73dba22d-e668-4b2d-84f3-a0beb1faebab ## After https://github.com/user-attachments/assets/6c8c6ffc-87f0-494f-bd41-7fde1f21d0e1 Fixes [[Navigation] Popping a nested route while the parent is rebuilding causes a flicker](flutter#178570)
…er#182315) Regression was introduced in [Cleans up navigator pop and remove logic](https://github.com/flutter/flutter/pull/175612/changes#top). That PR moved the `onDidRemovePage` call to `_flushHistoryUpdates` in phase `_RouteLifecycle.dispose`. But waiting until `dispose` causes potential problems if the widget is rebuilt in a phase preceding that (but after `pop` or `pushReplacement` has been called). So the outdated page remains in the pages list even after it has been marked for removal. This is causing the page to be pushed again before it is finally removed, causing the flicker. ## Before https://github.com/user-attachments/assets/73dba22d-e668-4b2d-84f3-a0beb1faebab ## After https://github.com/user-attachments/assets/6c8c6ffc-87f0-494f-bd41-7fde1f21d0e1 Fixes [[Navigation] Popping a nested route while the parent is rebuilding causes a flicker](flutter#178570)
…lutter#11060) Manual roll requested by tarrinneal@google.com flutter/flutter@6e4a481...c023e5b 2026-02-18 zhongliu88889@gmail.com [web] Pass form validation errors to screen readers via aria-description (flutter/flutter#180556) 2026-02-18 engine-flutter-autoroll@skia.org Roll Packages from f83926f to 59f905c (10 revisions) (flutter/flutter#182547) 2026-02-18 104147021+MohammedTarigg@users.noreply.github.com flutter_tools: Copy vendored frameworks from plugin podspecs in ios/macos-framework builds (flutter/flutter#180135) 2026-02-18 fluttergithubbot@gmail.com Marks Windows framework_tests_misc_leak_tracking to be unflaky (flutter/flutter#182534) 2026-02-18 brackenavaron@gmail.com Allow TabBar to receive a TabBarScrollController (flutter/flutter#180389) 2026-02-18 brackenavaron@gmail.com Clean up cross imports in single_child_scroll_view_test.dart, decorated_sliver_test.dart, draggable_scrollable_sheet_test.dart (flutter/flutter#181613) 2026-02-18 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from mcN42vw48OPH3JDNm... to Ihau0pUz3u5ajw42u... (flutter/flutter#182530) 2026-02-18 scheglov@google.com Analyzer, require 10.1.0, fix deprecations in dependency_graph.dart (flutter/flutter#182507) 2026-02-17 34465683+rkishan516@users.noreply.github.com Refactor: Remove material from actions test (flutter/flutter#181702) 2026-02-17 jhy03261997@gmail.com [a11y] RangeSlider mouse interaction should change keyboard focus (flutter/flutter#182185) 2026-02-17 116356835+AbdeMohlbi@users.noreply.github.com Remove more getters from userMessages class (flutter/flutter#182166) 2026-02-17 evanwall@buffalo.edu Implement getUniformMatX and getUniformMatXArray functionality on web (flutter/flutter#182249) 2026-02-17 victorsanniay@gmail.com Do not wait until dispose before removing replaced/popped page (flutter/flutter#182315) 2026-02-17 iliyazelenkog@gmail.com Add contentTextStyle support to SimpleDialog (flutter/flutter#178824) 2026-02-17 alex.medinsh@gmail.com Filter error messages from `emulator -list-avds` output (flutter/flutter#180802) 2026-02-17 brackenavaron@gmail.com [Reland] Cupertino cross imports (flutter/flutter#182416) 2026-02-17 engine-flutter-autoroll@skia.org Roll Packages from 09104b0 to f83926f (1 revision) (flutter/flutter#182504) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC stuartmorgan@google.com,tarrinneal@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…er#182315) Regression was introduced in [Cleans up navigator pop and remove logic](https://github.com/flutter/flutter/pull/175612/changes#top). That PR moved the `onDidRemovePage` call to `_flushHistoryUpdates` in phase `_RouteLifecycle.dispose`. But waiting until `dispose` causes potential problems if the widget is rebuilt in a phase preceding that (but after `pop` or `pushReplacement` has been called). So the outdated page remains in the pages list even after it has been marked for removal. This is causing the page to be pushed again before it is finally removed, causing the flicker. ## Before https://github.com/user-attachments/assets/73dba22d-e668-4b2d-84f3-a0beb1faebab ## After https://github.com/user-attachments/assets/6c8c6ffc-87f0-494f-bd41-7fde1f21d0e1 Fixes [[Navigation] Popping a nested route while the parent is rebuilding causes a flicker](flutter#178570)
…lutter#11060) Manual roll requested by tarrinneal@google.com flutter/flutter@6e4a481...c023e5b 2026-02-18 zhongliu88889@gmail.com [web] Pass form validation errors to screen readers via aria-description (flutter/flutter#180556) 2026-02-18 engine-flutter-autoroll@skia.org Roll Packages from f83926f to 59f905c (10 revisions) (flutter/flutter#182547) 2026-02-18 104147021+MohammedTarigg@users.noreply.github.com flutter_tools: Copy vendored frameworks from plugin podspecs in ios/macos-framework builds (flutter/flutter#180135) 2026-02-18 fluttergithubbot@gmail.com Marks Windows framework_tests_misc_leak_tracking to be unflaky (flutter/flutter#182534) 2026-02-18 brackenavaron@gmail.com Allow TabBar to receive a TabBarScrollController (flutter/flutter#180389) 2026-02-18 brackenavaron@gmail.com Clean up cross imports in single_child_scroll_view_test.dart, decorated_sliver_test.dart, draggable_scrollable_sheet_test.dart (flutter/flutter#181613) 2026-02-18 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from mcN42vw48OPH3JDNm... to Ihau0pUz3u5ajw42u... (flutter/flutter#182530) 2026-02-18 scheglov@google.com Analyzer, require 10.1.0, fix deprecations in dependency_graph.dart (flutter/flutter#182507) 2026-02-17 34465683+rkishan516@users.noreply.github.com Refactor: Remove material from actions test (flutter/flutter#181702) 2026-02-17 jhy03261997@gmail.com [a11y] RangeSlider mouse interaction should change keyboard focus (flutter/flutter#182185) 2026-02-17 116356835+AbdeMohlbi@users.noreply.github.com Remove more getters from userMessages class (flutter/flutter#182166) 2026-02-17 evanwall@buffalo.edu Implement getUniformMatX and getUniformMatXArray functionality on web (flutter/flutter#182249) 2026-02-17 victorsanniay@gmail.com Do not wait until dispose before removing replaced/popped page (flutter/flutter#182315) 2026-02-17 iliyazelenkog@gmail.com Add contentTextStyle support to SimpleDialog (flutter/flutter#178824) 2026-02-17 alex.medinsh@gmail.com Filter error messages from `emulator -list-avds` output (flutter/flutter#180802) 2026-02-17 brackenavaron@gmail.com [Reland] Cupertino cross imports (flutter/flutter#182416) 2026-02-17 engine-flutter-autoroll@skia.org Roll Packages from 09104b0 to f83926f (1 revision) (flutter/flutter#182504) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC stuartmorgan@google.com,tarrinneal@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Regression was introduced in Cleans up navigator pop and remove logic.
That PR moved the
onDidRemovePagecall to_flushHistoryUpdatesin phase_RouteLifecycle.dispose. But waiting untildisposecauses potential problems if the widget is rebuilt in a phase preceding that (but afterpoporpushReplacementhas been called). So the outdated page remains in the pages list even after it has been marked for removal.This is causing the page to be pushed again before it is finally removed, causing the flicker.
Before
bad.navigator.mov
After
good.navigator.mov
Fixes [Navigation] Popping a nested route while the parent is rebuilding causes a flicker