MediaQuery.of should no longer be a default tool in your Flutter toolbox.
Why? Well, if you’ve been using MediaQuery.of(context)
religiously, you might be introducing unnecessary rebuilds into your app. This leads to inefficiencies that can slow down your app and cause performance hiccups, especially in complex UIs.
Instead of falling into this trap, I’m going to show you 15 more efficient alternatives that will streamline your code and optimize your app’s performance.
By the end of this article, you'll have learned how to write cleaner and more efficient Flutter code with the latest context-specific getters. Ready to optimize your app? Let’s dive in!
What Is MediaQuery?
MediaQuery
is a class in Flutter that gives you access to essential device information such as screen size, device orientation, text scaling factor, and more. It’s often used in Flutter apps to make your UI adaptive across various devices.
Some typical use cases of MediaQuery
include:
- Screen Size: Detecting the device's width and height.
- Device Orientation: Checking if the device is in portrait or landscape mode.
- Text Scaling: Adjusting text size based on user preferences.
- Insets (e.g., Keyboard): Knowing when the keyboard is shown or system bars are present.
- Dark Mode Detection: Identifying whether the system is in light or dark mode.
- Accessibility Navigation: Understanding if accessibility features, like VoiceOver, are active.
- Reduced Animations: Determining if users prefer reduced animations.
But here's the problem: using MediaQuery.of(context)
can trigger widget rebuilds unnecessarily, especially if you're using it across multiple widgets.
Why does this happen? MediaQuery.of(context)
returns a MediaQueryData
object containing multiple device properties (e.g., screen size, orientation). When any property in this object changes, Flutter rebuilds the widget, even if you're only using one specific property. This can cause unnecessary rebuilds and performance issues.
It’s time to move beyond MediaQuery.of
and try these newer, more efficient alternatives.
15 Better Alternatives to MediaQuery.of
1. Retrieving Screen Size
Use MediaQuery.sizeOf(context)
instead of MediaQuery.of(context).size
.
Example:
final size = MediaQuery.sizeOf(context);
final width = size.width;
final height = size.height;
return Container(
width: width * 0.8, // 80% of screen width
height: height * 0.3, // 30% of screen height
color: Colors.blue,
);
Benefit: It rebuilds the widget only when the screen size changes.
(For responsive layouts, a better option might be using LayoutBuilder
. Learn more on https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html)
And if you want to avoid exceptions when no MediaQuery
ancestor exists, use maybeSizeOf(context)
.
2. Device Orientation
Use MediaQuery.orientationOf(context)
instead of MediaQuery.of(context).orientation
.
Example:
final orientation = MediaQuery.orientationOf(context);
return orientation == Orientation.portrait
? Column(children: [...])
: Row(children: [...]);
Benefit: Rebuilds only when the device orientation changes.
For cases without a MediaQuery
ancestor, use maybeOrientationOf(context)
.
3. Text Scaling Factor
Use MediaQuery.textScalerOf(context)
instead of MediaQuery.of(context).textScaleFactor
.
Example:
final textScaleFactor = MediaQuery.textScalerOf(context);
return Text(
'Responsive Text',
style: TextStyle(fontSize: 16 * textScaleFactor),
);
Benefit: It listens only to changes in the text scaling factor, preventing unnecessary rebuilds.
Use maybeTextScalerOf(context)
if you don’t want it to throw an error.
4. System Padding (Insets)
Use MediaQuery.viewInsetsOf(context)
instead of MediaQuery.of(context).viewInsets
.
Example:
final insets = MediaQuery.viewInsetsOf(context);
return Padding(
padding: EdgeInsets.only(bottom: insets.bottom),
child: TextField(),
);
Benefit: Reacts only when insets like the keyboard visibility change.
For a null-safe alternative, use maybeViewInsetsOf(context)
.
5. Dark Mode Detection (Brightness)
Use MediaQuery.platformBrightnessOf(context)
instead of MediaQuery.of(context).platformBrightness
.
Example:
final brightness = MediaQuery.platformBrightnessOf(context);
return brightness == Brightness.dark
? ThemeData.dark()
: ThemeData.light();
Benefit: Rebuilds only when the system changes between dark and light mode.
Use maybePlatformBrightnessOf(context)
for additional safety.
6. Handling Accessibility Navigation
Use MediaQuery.accessibleNavigationOf(context)
instead of MediaQuery.of(context).accessibleNavigation
.
Example:
final accessibleNavigation = MediaQuery.accessibleNavigationOf(context);
return accessibleNavigation
? Text('VoiceOver is enabled')
: Text('Normal mode');
Benefit: Detects accessibility navigation changes without triggering unwanted rebuilds.
Use maybeAccessibleNavigationOf(context)
to return null when no MediaQuery
ancestor is found.
7. Handling Device Pixel Ratio
Use MediaQuery.devicePixelRatioOf(context)
instead of MediaQuery.of(context).devicePixelRatio
.
Example:
final pixelRatio = MediaQuery.devicePixelRatioOf(context);
return Container(
width: 100 * pixelRatio,
height: 100 * pixelRatio,
);
Benefit: Updates only when the pixel density changes.
For a null-safe version, use maybeDevicePixelRatioOf(context)
.
8. Handling Bold Text Accessibility
Use MediaQuery.boldTextOf(context)
instead of MediaQuery.of(context).boldText
.
Example:
final boldText = MediaQuery.boldTextOf(context);
return Text(
'Accessible Text',
style: TextStyle(fontWeight: boldText ? FontWeight.bold : FontWeight.normal),
);
Benefit: Detects changes in bold text accessibility without unnecessary rebuilds.
For safer handling, use maybeBoldTextOf(context)
.
9. Detecting Animation Preferences
Use MediaQuery.disableAnimationsOf(context)
instead of MediaQuery.of(context).disableAnimations
.
Example:
final disableAnimations = MediaQuery.disableAnimationsOf(context);
return disableAnimations
? Container()
: AnimatedOpacity(
opacity: 1.0,
duration: Duration(seconds: 2),
child: Text('Animation'),
);
Benefit: Rebuilds the widget only when the user’s animation preferences change.
Use maybeDisableAnimationsOf(context)
for null safety.
10. Detecting High Contrast Mode
Use MediaQuery.highContrastOf(context)
instead of MediaQuery.of(context).highContrast
.
Example:
final highContrast = MediaQuery.highContrastOf(context);
return highContrast
? Text('High Contrast Text', style: TextStyle(color: Colors.black))
: Text('Normal Contrast Text', style: TextStyle(color: Colors.grey));
Benefit: Updates only when high contrast mode changes.
For a null-safe version, use maybeHighContrastOf(context)
.
11. Handling Inverted Colors
Use MediaQuery.invertColorsOf(context)
instead of MediaQuery.of(context).invertColors
.
Example:
final invertColors = MediaQuery.invertColorsOf(context);
return ColorFiltered(
colorFilter: invertColors
? ColorFilter.mode(Colors.white, BlendMode.difference)
: ColorFilter.mode(Colors.transparent, BlendMode.multiply),
child: Image.asset('image.png'),
);
Benefit: Reacts only when color inversion changes.
For null safety, use maybeInvertColorsOf(context)
.
12. Handling Gesture Settings
Use MediaQuery.gestureSettingsOf(context)
instead of MediaQuery.of(context).gestureSettings
.
Example:
final gestureSettings = MediaQuery.gestureSettingsOf(context);
return gestureSettings.touchSlop > 0
? Text('Gesture Detected')
: Text('No Gesture Detected');
Benefit: Listens for changes in gesture settings without triggering unnecessary rebuilds.
Use maybeGestureSettingsOf(context)
if you need null safety.
13. Detecting Display Features
Use MediaQuery.displayFeaturesOf(context)
instead of MediaQuery.of(context).displayFeatures
.
Example:
final displayFeatures = MediaQuery.displayFeaturesOf(context);
return Text(displayFeatures.isNotEmpty ? 'Cutout Detected' : 'No Cutout');
Benefit: Updates only when display features like cutouts or foldables change.
For null safety, use maybeDisplayFeaturesOf(context)
.
14. Handling System Padding
Use MediaQuery.paddingOf(context)
instead of MediaQuery.of(context).padding
.
Example:
final padding = MediaQuery.paddingOf(context);
return Padding(
padding: EdgeInsets.all(padding.top),
child: Text('Padded Text'),
);
Benefit: Rebuilds only when system UI padding changes.
To avoid exceptions, use maybePaddingOf(context)
.
15. Detecting System Gesture Insets
Use MediaQuery.systemGestureInsetsOf(context)
instead of MediaQuery.of(context).systemGestureInsets
.
Example:
final systemGestureInsets = MediaQuery.systemGestureInsetsOf(context);
return Padding(
padding: systemGestureInsets,
child: Text('Gesture Insets Applied'),
);
Benefit: Reacts only when system gesture insets change.
For a safer implementation, use maybeSystemGestureInsetsOf(context)
.
Conclusion
There you have it! 15 better alternatives to using MediaQuery.of(context)
that can significantly improve your app’s performance by preventing unnecessary widget rebuilds. These new methods are more specific and efficient, and they’ll help you build Flutter apps with ease.
Try them out and let me know how they work for you! As always, feel free to reach out if you have any questions or want to share your results. Happy coding! 🚀
Top comments (0)