为何在MyApp/FirstPage中需用Builder才能使用MediaQuery?是否仍需添加?
MediaQuery.of(context) Hey there! Let's break down your questions using your code examples to make everything clear and straightforward.
1. Why Builder is required in FirstPage/FirstPageUI?
First, let's look at how your FirstPage is structured:
class _FirstPageState extends State<FirstPage> { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold(body: FirstPageUI().getFirstPageUIWidget())); } }
The context parameter in this build method belongs to _FirstPageState, which sits outside the MaterialApp widget you're returning.
When you call FirstPageUI().getFirstPageUIWidget(), this method doesn't receive any valid BuildContext that's inside the MaterialApp tree. Since MediaQuery.of(context) needs to traverse the widget tree upwards to find the MediaQuery widget (automatically inserted by MaterialApp), using a context outside MaterialApp would throw an error.
The Builder widget fixes this by creating a new BuildContext that's part of the MaterialApp subtree. This fresh context can successfully locate the MediaQuery data needed to get MediaQuery.of(context).size.
If you tried to use the FirstPage's context directly (without Builder), you'd get an error like:
Could not find the correct Provider
above this FirstPageUI Widget
2. Why SecondPage doesn't need Builder?
Looking at your SecondPage code:
class _SecondPageState extends State<SecondPage> { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: SecondPageUI(context).getSecondPageUIWidget() ), ); } }
First, a quick best practice note: you shouldn't create a second MaterialApp here. A Flutter app should only have one root MaterialApp (the one in FirstPage), as it handles global configurations like theme, routes, and provides the root MediaQuery.
That said, the reason MediaQuery.of(context) works here is that the context you're passing to SecondPageUI belongs to _SecondPageState, which is part of the navigation stack under the original FirstPage's MaterialApp. When you call MediaQuery.of(context), it traverses up the tree past the Navigator and finds the MediaQuery from the root MaterialApp.
Even though you have an extra MaterialApp in SecondPage, it doesn't break things because the context still has access to the root MediaQuery above it. But removing this redundant MaterialApp would make your code cleaner and more aligned with Flutter standards.
3. Should you add Builder to other pages?
No, you don't need to add Builder to other pages as long as you're using a BuildContext that's part of the widget tree under the root MaterialApp (or any widget that provides MediaQuery).
Builder is only necessary when:
- The context you have is outside the subtree that contains the
MediaQuery(or other inherited widget you need) - You need to create a new context at a specific point in the tree to access inherited data from parent widgets above that point
In your SecondPage case, since the context is already part of the root MaterialApp's tree, you can safely use it without wrapping everything in Builder.
Quick Fix for Your Code
To make your code more correct, remove the MaterialApp from SecondPage:
class _SecondPageState extends State<SecondPage> { @override Widget build(BuildContext context) { return Scaffold( body: SecondPageUI(context).getSecondPageUIWidget() ); } }
This way, you're using the single root MaterialApp and keeping your widget tree clean and efficient.
内容的提问来源于stack exchange,提问作者John

