DEV Community

Cover image for Stop Using MediaQuery.of! Try These 15 More Efficient Alternatives Instead
Flutter with Caio
Flutter with Caio

Posted on • Originally published at Medium

Stop Using MediaQuery.of! Try These 15 More Efficient Alternatives Instead

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:

  1. Screen Size: Detecting the device's width and height.
  2. Device Orientation: Checking if the device is in portrait or landscape mode.
  3. Text Scaling: Adjusting text size based on user preferences.
  4. Insets (e.g., Keyboard): Knowing when the keyboard is shown or system bars are present.
  5. Dark Mode Detection: Identifying whether the system is in light or dark mode.
  6. Accessibility Navigation: Understanding if accessibility features, like VoiceOver, are active.
  7. 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,
);
Enter fullscreen mode Exit fullscreen mode

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: [...]);
Enter fullscreen mode Exit fullscreen mode

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),
);
Enter fullscreen mode Exit fullscreen mode

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(),
);
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen 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,
);
Enter fullscreen mode Exit fullscreen mode

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),
);
Enter fullscreen mode Exit fullscreen mode

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'),
    );
Enter fullscreen mode Exit fullscreen mode

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));
Enter fullscreen mode Exit fullscreen mode

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'),
);
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

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'),
);
Enter fullscreen mode Exit fullscreen mode

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'),
);
Enter fullscreen mode Exit fullscreen mode

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)