TL;DR: Prefer using classes over functions to make reusable widget-tree.
EDIT: To make up for some misunderstanding:
This is not about functions causing problems, but classes solving some.
Flutter wouldn't have StatelessWidget if a function could do the same thing.
Similarly, it is mainly directed at public widgets, made to be reused. It doesn't matter as much for private functions made to be used only once – although being aware of this behavior is still good.
There is an important difference between using functions instead of classes, that is: The framework is unaware of functions, but can see classes.
Consider the following "widget" function:
Widget functionWidget({ Widget child}) {
return Container(child: child);
}
used this way:
functionWidget(
child: functionWidget(),
);
And it's class equivalent:
class ClassWidget extends StatelessWidget {
final Widget child;
const ClassWidget({Key key, this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
child: child,
);
}
}
used like that:
new ClassWidget(
child: new ClassWidget(),
);
On paper, both seem to do exactly the same thing: Create 2 Container
, with one nested into the other. But the reality is slightly different.
In the case of functions, the generated widget tree looks like this:
Container
Container
While with classes, the widget tree is:
ClassWidget
Container
ClassWidget
Container
This is important because it changes how the framework behaves when updating a widget.
Why that matters
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.
Here are a few interactive examples on Dartpad that you can run yourself to better understand the issues:
Conclusion
Here's a curated list of the differences between using functions and classes:
- Classes:
- allow performance optimization (const constructor, more granular rebuild)
- ensure that switching between two different layouts correctly disposes of the resources (functions may reuse some previous state)
- ensures that hot-reload works properly (using functions could break hot-reload for
showDialogs
& similar)
- are integrated into the widget inspector.
- We see
ClassWidget
in the widget-tree showed by the devtool, which
helps understanding what is on screen
- We can override debugFillProperties to print what the parameters passed to a widget are
- better error messages
If an exception happens (like ProviderNotFound), the framework will give you the name of the currently building widget.
If you've split your widget tree only in functions + Builder
, your errors won't have a helpful name
- can define keys
- can use the context API
- Functions:
Overall, it is considered a bad practice to use functions over classes for reusing widgets because of these reasons.
You can, but it may bite you in the future.