How to achieve Provider.select behaviour using built in InheritedWidget like MediaQuery?

114 Views Asked by At

In my chat app every message depends on MediaQuery (font scaling). When keyboard is appear on Android 11+ then bottom insets in MediaQuery are animated from 0 to keyboard height. It cause unwanted rebuilds of all messages, but they depends only from font scaling. With Provider library I can use method select for this case. How to achieve same result with MediaQuery?

1

There are 1 best solutions below

2
WSBT On

Since there is no code provided in the question, I'll try to help based on the question description. I see multiple potential issues here.

  1. The viewInsets animation of MediaQuery is probably not what's causing the rebuild.

One might think the dependence on MediaQuery's textScaleFactor is the cause of rebuilds whenever MediaQuery changes, but I'm willing to bet that, even if you remove the dependency and just simply return an empty Container, it would still rebuild during the keyboard collapse animation.

  1. So what's causing the rebuilds? Probably the fact that the app area expanded/shrank due to keyboards popping up.

For example, the total height of a Scaffold would actually shrink, when a keyboard is visible. If you don't want this, you can set resizeToAvoidBottomInset for it, like so:

return Scaffold(
  resizeToAvoidBottomInset: false,
  // ...
  1. You can access text scale factor much earlier in the widget tree.

If you really want to only get the text scale factor of MediaQuery, you can access it from much earlier in the widget tree, and save it as a variable, and pass it down however you like (provider, etc):

final scaleFactor = MediaQuery.of(context).textScaleFactor;
print(scaleFactor);
  1. You can remove viewInsets from MediaQuery if you really want to.

If you want to remove viewInsets (or set it to a fixed value), you can override it by inserting another MediaQuery on the tree:

return MediaQuery(
  data: MediaQuery.of(context).copyWith(
    viewInsets: EdgeInsets.zero,
  ),
  child: Container( /* always zero insets */ ),
);
  1. Rebuilding shouldn't be a problem.

Lastly, Flutter widgets should be prepared to be rebuilt at any time and shouldn't cause any issues. So I assume you are only noticing your widgets being rebuilt because Flutter Inspector, or you added a print in the build method, and noticed a bunch of prints in the console. I wouldn't worry too much about it unless you are actually experiencing REAL performance issues. However, if your widgets don't behave properly when rebuilt at "unexpected times", you should fix that, because Flutter WILL rebuild your widgets all the time, not just when the keyboard is collapsed :D