-
Notifications
You must be signed in to change notification settings - Fork 28.5k
MediaQuery picks up view data changes #166498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MediaQuery picks up view data changes #166498
Conversation
@@ -1882,7 +1882,9 @@ class _MediaQueryFromViewState extends State<_MediaQueryFromView> with WidgetsBi | |||
if (widget.ignoreParentData != oldWidget.ignoreParentData) { | |||
_updateParentData(); | |||
} | |||
if (_data == null || oldWidget.view != widget.view) { | |||
if (_data == null || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A pattern I notice in this file is didChange*()
which updates the MediaQueryData
. These notifications are sent from the embedder. I wonder if that's the pattern we should be following here, what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah you're saying that I could add a WidgetsBindingObserver.didChangeViewData and call that instead of didChangeMetrics? In this case I only need the method for tests, so I worry about bloating the WidgetsBindingObserver API just for my that. And anyway I'd still have to use my hacky _updateMediaQueryFromView method in the tests.
I looked into seeing if there's a better way to send these kinds of messages from the embedder to trigger didChangeMetrics instead of directly calling it on the WidgetsBindingObserver instance, but I found other tests were doing the same thing as me, e.g.
state.didChangeMetrics(); |
It seems to me like this should be checking if the data has changed anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After talking to @Renzo-Olivares offline, I'm now trying to directly trigger _updateData when supportsShowingContextMenu changes. Inspired by #166836.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Renzo-Olivares I've set this up so that I can trigger the change through the PlatformDispatcher, similar to changes to the theme brightness etc. Let me know what you think.
898b394
to
e054768
Compare
@@ -262,6 +262,57 @@ void main() { | |||
}, | |||
); | |||
|
|||
testWidgets('MediaQueryData.fromView picks up new view data when rebuilding', ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: should we rename this test to mention support showing system context menu.
|
||
tester.platformDispatcher.supportsShowingSystemContextMenu = true; | ||
tester.binding.handleSupportsShowingSystemContextMenuChanged(); | ||
addTearDown(() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can these be added to the addTearDown
at the top of this test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes good call.
expect(datas1.first.supportsShowingSystemContextMenu, isFalse); | ||
|
||
tester.platformDispatcher.supportsShowingSystemContextMenu = true; | ||
tester.binding.handleSupportsShowingSystemContextMenuChanged(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this have to be explicitly called?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, otherwise the MediaQuery does not update the data that it gets from the view. This is the same problem I was trying to solve in other ways in #166498 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it looks like your current implementation is in line with the pattern we use for other APIs in platformDispatcher
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious why it doesn't work like in this test
flutter/packages/flutter/test/widgets/media_query_test.dart
Lines 507 to 510 in e841350
expect(data.platformBrightness, Brightness.dark); | |
tester.platformDispatcher.platformBrightnessTestValue = Brightness.light; | |
await tester.pump(); | |
expect(data.platformBrightness, Brightness.dark); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That test confuses me because it sets the brightness to light
, then expects that it's still dark
...
But this is my understanding of the situation as I've been working on this PR. Each time you test a file with flutter test
, a single top-level View gets created. When you run pumpWidgets
, those widgets get put into this View, and the View has its own top-level MediaQuery widget. So even though you might call pumpWidgets
with a whole new MaterialApp, you still have the same old top level MediaQuery widget.
When I change the view data with something like:
tester.platformDispatcher.supportsShowingSystemContextMenu = true;
That MediaQuery widget does not automatically update. It still has its old view data until you call _updateData one way or another. In my case, I've set up handleSupportsShowingSystemContextMenuChanged to call _updateData.
Note that this situation doesn't matter when running a single test. If you set tester.platformDispatcher.supportsShowingSystemContextMenu in the initial setup
before that top-level MedaiQuery.fromView gets instantiated, then it will pick up your value when it does get created.
This fixes a bug in MediaQuery's update logic and removes some now-unnecessary workaround code. Fixes flutter#165519 Discovered in flutter#165354 (comment)
This fixes a bug in MediaQuery's update logic and removes some now-unnecessary workaround code. Fixes flutter#165519 Discovered in flutter#165354 (comment)
This fixes a bug in MediaQuery's update logic and removes some now-unnecessary workaround code.
Fixes #165519
Discovered in #165354 (comment)