Numerous questions relating to building Flutter UIs come down to the wrong BuildContext
(such as showing a SnackBar
). The answers usually offer either of using a Builder
or using a GlobalKey
. Both work, but I noticed that the documentation for GlobalKey states:
Global keys are relatively expensive. If you don't need any of the features listed above, consider using a
Key
,ValueKey
,ObjectKey
, orUniqueKey
instead.
The features referred to are unique identification and subtree re-parenting. Is the "relative expense" of using a GlobalKey
for these circumstances reason enough to use a Builder
instead?
Global keys provide access to other objects that are associated with those elements, such as BuildContext. For StatefulWidgets, global keys also provide access to State. Widgets that have global keys reparent their subtrees when they are moved from one location in the tree to another location in the tree.
The global key can be used to access a state of another widget from anywhere in the widget tree but it is expensive and there are better ways to do that such as Providers, Inherited Widgets, etc. But it does have a few good and valid use cases such as Form validation.
The real reason we tend to avoid GlobalKey
is not about performance. It is more related to the fact that it breaks a few patterns in flutter.
Widgets by definition should not be able to access concrete information of other widgets (such as their size or position). And GlobalKey
grant the ability to access such information; allowing peoples to do anti-pattern stuff.
Think of GlobalKey
as a mean to eject the reactive layer of Flutter.
A few examples of what peoples are tempted to do using GlobalKey
:
GlobalKey
. Used as a mean to not lift the state up. Making interaction between widgets hard to predict, as the relationship isn't one-sided anymore (parent -> children becomes a two-way relationship)GlobalKey
to compute the size of a layout. Then trigger a re-render with this information. This instead is the role of RenderObject
and shouldn't be done in widgets. It makes layout much harder to maintainBuilder
and similar on the other hand don't break these patterns. As, by definition Builder
does nothing. It's just a neat way of using a different BuildContext
.
This usually means that if you can solve your layout problem using Builder
instead of GlobalKey
, you're on the right track to a maintainable layout.
When to use GlobalKey
then?
Well, if you can, never. Try to instead use things such as context.ancestorStateOfType
or context.inheritWidgetOfExtactType
. You may also want to consider creating a custom RenderObject
for a specific layout. RenderObject
combined with parentData
may also be what you want if you need a relationship between parent/children
This can more complicated though. It can consume more time than you want. Or you may fall into an edge-case that is hard to implement using the current API.
In such situations, it is ok to use GlobalKey
as long as you know the potential consequences.
GlobalKey
being expensive is most likely related to situations where you might need lots of keys, like for the children of a ListView
.
I doubt the cost of a GlobalKey
for a SnackBar
will matter. It's unlikely that you create a lot of them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With