Skip to content

Conversation

@YeungKC
Copy link
Member

@YeungKC YeungKC commented Oct 25, 2024

This commit refactors the _MenuAnchorState class in menu_anchor.dart to include a check for the mounted state and the scheduler phase before calling setState(). This ensures that UI updates are only performed when the widget is still mounted and not during the persistent callbacks phase. Additionally, a new test case is added in menu_anchor_test.dart to verify that the isOpen state of the MenuAnchor widget is updated correctly when the button is pressed.

Fix: #157606

Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.

List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.

If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

This commit refactors the `_MenuAnchorState` class in `menu_anchor.dart` to include a check for the mounted state and the scheduler phase before calling `setState()`. This ensures that UI updates are only performed when the widget is still mounted and not during the persistent callbacks phase. Additionally, a new test case is added in `menu_anchor_test.dart` to verify that the `isOpen` state of the `MenuAnchor` widget is updated correctly when the button is pressed.

Fix: flutter#157606
@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Oct 25, 2024
@YeungKC YeungKC requested a review from nate-thegrate October 25, 2024 16:52
Copy link
Contributor

@nate-thegrate nate-thegrate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix, this looks awesome!

Comment on lines +580 to +584
if (mounted && SchedulerBinding.instance.schedulerPhase != SchedulerPhase.persistentCallbacks) {
setState(() {
// Mark dirty to ensure UI updates
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had no idea that the SchedulerPhase could be used this way, thanks!

@YeungKC YeungKC marked this pull request as ready for review October 25, 2024 17:12
@YeungKC YeungKC requested a review from dkwingsmt October 25, 2024 17:14
@YeungKC YeungKC changed the title Fix menu anchor state handling and add test case Fix menu anchor state handling Oct 25, 2024
@nate-thegrate
Copy link
Contributor

Actually, quick question before we land this one—there looks to be a _MenuAnchorScope class set up to notify when the value of isOpen changes.

class _MenuAnchorScope extends InheritedWidget {
const _MenuAnchorScope({
required super.child,
required this.anchorKey,
required this.anchor,
required this.isOpen,
});
final GlobalKey anchorKey;
final _MenuAnchorState anchor;
final bool isOpen;
@override
bool updateShouldNotify(_MenuAnchorScope oldWidget) {
return anchorKey != oldWidget.anchorKey
|| anchor != oldWidget.anchor
|| isOpen != oldWidget.isOpen;
}
}

Currently it doesn't look like the inherited widget rebuilds when the menu is opened; maybe we should remove the isOpen field to prevent confusion.

@YeungKC
Copy link
Member Author

YeungKC commented Oct 25, 2024

The _MenuAnchorScope is indeed designed to notify its dependents when the isOpen state changes, but this notification doesn't directly trigger a rebuild of the builder. Instead, it triggers the didChangeDependencies method in the dependent widgets.

@nate-thegrate
Copy link
Contributor

The _MenuAnchorScope is indeed designed to notify its dependents when the isOpen state changes, but this notification doesn't directly trigger a rebuild of the builder. Instead, it triggers the didChangeDependencies method in the dependent widgets.

True that!

I think what I'm trying to get to is: this bug indicates that _MenuAnchorState does not rebuild when the menu is opened.

Perhaps it'd be good to remove the _MenuAnchorScope.isOpen flag, since currently it isn't set up to report accurate values. Alternatively, we could rework _MenuAnchorScope so it's rebuilt when the controller opens/closes.

@YeungKC
Copy link
Member Author

YeungKC commented Oct 25, 2024

Consider a scenario where we're not using the builder pattern, but instead using a simple child widget. After this PR is merged, such a child widget would still be able to detect updates through didChangeDependencies.

@nate-thegrate
Copy link
Contributor

Consider a scenario where we're not using the builder pattern, but instead using a simple child widget. After this PR is merged, such a child widget would still be able to detect updates through didChangeDependencies.

Perhaps so, though we'd need some way to let the child depend on _MenuAnchorScope through a public API.


My concern is:

context.dependOnInheritedWidgetOfExactType<_MenuAnchorScope>()!.isOpen;

In order for this value to be accurate, the inherited widget needs to be rebuilt when the controller opens/closes. And since rebuilding the _MenuAnchorState would also involve re-evaluating the builder, I believe this bug is evidence that _MenuAnchorScope.isOpen is sometimes inaccurate.

Since it's a private class and isOpen isn't accessed anywhere, perhaps we should remove the field.

@YeungKC
Copy link
Member Author

YeungKC commented Oct 25, 2024

I don't believe that _MenuAnchorScope.isOpen would be inaccurate. Could you provide a test case demonstrating this?

While I understand that _MenuAnchorScope.isOpen can't be accessed directly, triggering didChangeDependencies seems more "correct" to me. If I were to use didChangeDependencies as a trigger and then check the controller's isOpen state, that would also be a valid approach.

I think we may be straying too far from the original intent of this PR. Perhaps it would be better to open a separate issue to discuss this particular concern in more depth.

@nate-thegrate
Copy link
Contributor

I think we may be straying too far from the original intent of this PR.

Fair point, especially if we end up removing the _MenuAnchorScope.isOpen field.

If we decide to keep it, however, updating _MenuAnchorState to rebuild when its value changes would mean that the changes in this PR are unnecessary.

@YeungKC
Copy link
Member Author

YeungKC commented Oct 25, 2024

I see your point. However, I think there's an important aspect to consider here. Without this PR, the _MenuAnchorScope wouldn't update its isOpen state, and consequently, updateShouldNotify wouldn't return true when the menu opens or closes.

@nate-thegrate
Copy link
Contributor

I see your point. However, I think there's an important aspect to consider here. Without this PR, the _MenuAnchorScope wouldn't update its isOpen state, and consequently, updateShouldNotify wouldn't return true when the menu opens or closes.

100% agree. In my mind I was thinking "if _MenuAnchorScope is updated to rebuild when the controller opens/closes, then we could just add a dependency to the builder"

What didn't connect for me till just now: since this change calls _MenuAnchorState.setState, the inherited widget is now guaranteed to be up-to-date, so that's pretty awesome 👍

Copy link
Contributor

@bleroux bleroux left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks for the contribution.

@bleroux bleroux added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 30, 2024
@auto-submit auto-submit bot merged commit ec50578 into flutter:master Oct 30, 2024
73 checks passed
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Oct 30, 2024
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Oct 30, 2024
flutter/flutter@42132e8...fe71cad

2024-10-30 [email protected] Update CHANGELOG.md to correct ios vs macos issue (flutter/flutter#157822)
2024-10-30 [email protected] Add ability to customize the default `Slider` padding (flutter/flutter#156143)
2024-10-30 [email protected] Fix menu anchor state handling (flutter/flutter#157612)
2024-10-30 [email protected] Add test for `interactive_viewer.0.dart` (flutter/flutter#157773)
2024-10-30 [email protected] Add test for `scroll_metrics_notification.0.dart` (flutter/flutter#157768)
2024-10-30 [email protected] Add boundary feature to the drag gesture. (flutter/flutter#147521)
2024-10-30 [email protected] Fix `ResizeImage` documentation (flutter/flutter#157619)
2024-10-29 [email protected] Roll Flutter Engine from 795b5492f1b9 to 999797a2f690 (1 revision) (flutter/flutter#157825)
2024-10-29 [email protected] Avoid labeling all PRs as 'text-input' (flutter/flutter#157805)
2024-10-29 [email protected] Roll Packages from e0c4f55 to 028027e (8 revisions) (flutter/flutter#157813)
2024-10-29 [email protected] Roll Flutter Engine from 725c8e4bc379 to 795b5492f1b9 (5 revisions) (flutter/flutter#157820)
2024-10-29 [email protected] Fix and remove a few `no-shuffle` tags in `flutter_tools`. (flutter/flutter#157656)

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 [email protected],[email protected] 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
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 12, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 13, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 13, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 6, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Mar 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MenuAnchor.builder does not update properly

3 participants