For various reasons, sometimes the build
method of my widgets is called again.
I know that it happens because a parent updated. But this causes undesired effects.
A typical situation where it causes problems is when using FutureBuilder
this way:
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: httpCall(),
builder: (context, snapshot) {
// create some layout here
},
);
}
In this example, if the build method were to be called again, it would trigger another http request. Which is undesired.
Considering this, how to deal with unwanted build? It there any way to prevent build call?
The build method is designed in such a way that it should be pure/without side effects. This is because many external factors can trigger a new widget build, such as:
Class.of(context)
pattern) changeThis means that the
build
method should not trigger an http call or modify any state.How is this related to the question?
The problem you are facing is that your build method has side-effects/is not pure, making extraneous build call troublesome.
Instead of preventing build call, you should make your build method pure, so that it can be called anytime without impact.
In the case of your example, you'd transform your widget into a
StatefulWidget
then extract that HTTP call to theinitState
of yourState
:When the instance of a widget stays the same; Flutter purposefully won't rebuild children. It implies that you can cache parts of your widget tree to prevent unnecessary rebuilds.
The easiest way is to use dart
const
constructors:Thanks to that
const
keyword, the instance ofDecoratedBox
will stay the same even if build were called hundreds of times.But you can achieve the same result manually:
In this example when StreamBuilder is notified of new values,
subtree
won't rebuild even if the StreamBuilder/Column do. It happens because thanks to the closure, the instance ofMyWidget
didn't change.This pattern is used a lot in animations. Typical users are
AnimatedBuilder
and all *Transition such asAlignTransition
.You could also store
subtree
into a field of your class, although less recommended as it breaks hot-reload.