Im unsure about wether caching a widget instance and reusing it in the build()
method makes a significant difference.
Suppose we have two widget classes:
class ParentWidget extends StatelessWidget {
ParentWidget({Key key})
: super(key: key);
@override
Widget build(BuildContext context) {
return Container( // or some other widgets that define the ui
child: ChildWidget(/*...*/),
);
}
}
class ChildWidget extends StatelessWidget {
ChildWidget({Key key}) : super(key: key); // no constant
@override
Widget build(BuildContext context) {
/*
* returns some Widget
*/
}
}
From my understanding, everytime Flutter calls build()
on the ParentWidget
, a new ChildWidget
is created and attached to the same Element in the element tree. Except if const ChildWidget
is available (e.g. ChildWidget
has a const constructor).
However, we can cache the child like so:
class ParentWidget extends StatelessWidget {
final Widget child;
ParentWidget({Key key})
: child = ChildWidget(/*...*/),
super(key: key);
@override
Widget build(BuildContext context) {
return Container(
// or some other widgets that define the ui
child: child, // <-- use child instead of ChildWidget()
);
}
}
From my understanding, the same widget will be used and no modification of the element tree has to be done by flutter. But I am unsure in which cases that matters.
Is there a significant difference between caching a widget and creating a new Widget with the same configuration? If so, is there a rule on when to cache widgets instead of reconstructing them?
Stateful widgets are useful when the part of the user interface you are describing can change dynamically, e.g. due to having an internal clock-driven state, or depending on some system state.
Using setState to rebuild widgets Flutter gives you access to setState() . In this case, we have to ensure setState() has the new values. When setState() is called, Flutter will know to get these new values and mark the widget that needs to be rebuilt.
A stateful widget is implemented by two classes: a subclass of StatefulWidget and a subclass of State . The state class contains the widget's mutable state and the widget's build() method. When the widget's state changes, the state object calls setState() , telling the framework to redraw the widget.
To create a stateful widget in a flutter, use the createState() method. The stateful widget is the widget that describes part of a user interface by building a constellation of other widgets that represent a user interface more concretely. A stateful Widget means a widget that has a mutable state.
In the documentation of StatefulWidget, it is recommended to cache a widget if the subtree represented by that widget does not change:
If a subtree does not change, cache the widget that represents that subtree and re-use it each time it can be used. It is massively more efficient for a widget to be re-used than for a new (but identically-configured) widget to be created. Factoring out the stateful part into a widget that takes a child argument is a common way of doing this.
I therefore conclude that whenever a Widget changes State, subtrees that do not change based on the state should be cached and reused.
However, the example declared in the question is not a situation in which choosing to cache the widget is a good option, as only the root of a not-changing subtree should be cached by the parent of that subtree. But as ParentWidget
is itself a StatelessWidget
, it will be part of a not-changing subtree each time ChildWidget
is. Therefore, some stateful Parent of ParentWidget
should be responsible for caching.
There can be a difference, if for example the child widget allocates resources or has a large subtree of children.
The official flutter api documentation does recommend caching in certain situations. But generally, it should not be the first thing to do, when trying to optimise your views.
Read the documentation on Stateful and Stateless widgets, in particular the "Performance Considerations" section has a lot of relevant further information. For example:
- If a subtree does not change, cache the widget that represents that subtree and re-use it each time it can be used.
- Use const widgets where possible. (This is equivalent to caching a widget and re-using it.)
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