Is there any difference, performance wise, in using a StatelessWidget
vs a function returning a Widget
?
I'm well aware of at least the differences pointed out in this flutter's repo issue which don't have a relationship with performance.
The fact is that I have some colleagues claiming that functional widgets
are worst in terms of performance but after reading a little bit about the subject I cannot find any conclusive piece of documentation that can give credit to that assertion so any kind of clarification regarding this matter will be very welcome!
As far as I can see the only difference between them would be in the case of using a const Widget
, which seems that would avoid the rebuilding phase.
By using functions to split your widget tree into multiple widgets, you expose yourself to bugs and miss on some performance optimizations. There is no guarantee that you will have bugs by using functions, but by using classes, you are guaranteed to not face these issues.
Stateless widget overrides the build() method and returns a widget. For example, we use Text or the Icon is our flutter application where the state of the widget does not change in the runtime. It is used when the UI depends on the information within the object itself.
Widgets are the central class hierarchy in the Flutter framework. A widget is an immutable description of part of a user interface. Widgets can be inflated into elements, which manage the underlying render tree. Widgets themselves have no mutable state (all their fields must be final).
First of all, I'd like to note that a package is available to make a StatelessWidget
from a function: functional_widget
The gain is performance is not necessarily true. It depends on how you use your widgets, mostly how you use them to manage your state.
By default, classes may degrade performances when opposed to functions in an application that doesn't utilize their power.
The real question is: What is their power?
Simple: Classes can update independently from each other. Functions cannot
It is possible for classes to partially update the widget tree.
Consider a widget that rebuilds every frame and returns its child:
class InfiniteLoop extends StatefulWidget { const InfiniteLoop({Key key, this.child}) : super(key: key); final Widget child; @override _InfiniteLoopState createState() => _InfiniteLoopState(); } class _InfiniteLoopState extends State<InfiniteLoop> { @override Widget build(BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {})); return widget.child; } }
Now if we wrap our whole application in that widget, what happens?
void main() => runApp(InfiniteLoop(child: MyApp()));
Nothing
Sure, you'll have one widget that rebuilds often in your tree. But in reality, the build
method of MyApp
will be called only once.
That's because Flutter is able to abort the tree rebuild when the instance of a widget doesn't change.
Classes can abuse of this optimization.
Using classes it is possible to cleverly split the rebuilding of your widget tree into independent parts.
It's not reasonable to list all the potential optimization factors that a class allow, as there are too many.
The following example is a widget that takes an int
and formats it into a Text
. The catch is, this widget will rebuild only if the int
passed change:
class Counter extends StatelessWidget { const Counter({Key key, this.value}) : super(key: key); final int value; @override Widget build(BuildContext context) { return Text(value.toString()); } @override bool operator ==(Object other) => identical(this, other) || (other is Counter && other.value == value); @override int get hashCode => value.hashCode; }
This works because Flutter uses the ==
operator to know if a widget should update or not (hence why const
constructor is a good optimization factor).
This is not the only solution, but it's a good example of something that functions can't do.
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