Boost Your Flutter App Performance With These 6 Tips
Introduction Link to heading
Get better scrolling and animations, less memory consumption, and more execution speed. Boost your Flutter app performance with these 6 tips. And if you want more, I have a free ebook with additional tips for you at the end!
Here are some easy-to-use best practices for Flutter apps when it’s all about performance. Use them if you notice any problems but don’t optimize prematurely. Flutter apps are fast by default and you won’t have any trouble usually. Here is how you can boost your Flutter app performance with these 6 tips.
Also, make sure to download my free ebook about Flutter performance tips. You can find the link at the end of this article.
Prefer StatelessWidget over StatefulWidget Link to heading
A StatelessWidget is faster than a StatefulWidget because it doesn’t need to manage state as the name implies. That’s why you should prefer it if possible. Choose a StatefulWidget when…
▶ you need a preparation function with initState()
▶ you need to dispose of resources with dispose()
▶ you need to trigger a widget rebuild with setState()
▶ your widget has changing variables (non-final) In all other situations, you should prefer a StatelessWidget.
⛔ Bad example
Dart
import 'package:flutter/widgets.dart';
class MyWidget extends StatefulWidget {
final String header;
final String subheader;
const MyWidget({Key? key, required this.header, required this.subheader}): super(key: key);
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
@override
Widget build(BuildContext context) {
return Column(children: [Text(widget.header), Text(widget.subheader)]);
}
}
✅ Good example
Dart
import 'package:flutter/widgets.dart';
class MyWidget extends StatelessWidget {
final String header;
final String subheader;
const MyWidget({Key? key, required this.header, required this.subheader}): super(key: key);
@override
Widget build(BuildContext context) {
return Column(children: [Text(header), Text(subheader)]);
}
}
Use builder constructors on long lists or grids Link to heading
When dealing with lists or grids with many items, it is recommended to use the builder constructors. Their advantage is that only visible elements are rendered. So if your list or grid is bigger than one device screen, you should choose this approach. For smaller lists and grids, the default constructors can also be used. This applies to all types of lists and grids like ListView, ReorderableListView, or GridView. Always check for a builder constructor and use it if possible.
✅ Good example
Dart
final List<int> _listItems = <int>[1, 2, 3, 4, 5, 6, 7, 8, 9];
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _listItems.length,
itemBuilder: (context, index) {
var item = _listItems[index];
return SizedBox(
height: 300, child: Center(child: Text(item.toString())));
}
);
}
Don’t use OpacityWidget Link to heading
The Opacity widget can cause performance issues when used with animations because all child widgets of the Opacity widget will also be rebuilt in every new frame. It is better to use AnimatedOpacity in this case. If you want to fade in an image, use the FadeInImage widget. If you want to have a color with opacity, draw a color with opacity.
⛔ Bad example
Dart
Opacity(opacity: 0.5, child: Container(color: Colors.red))
✅ Good example
Dart
Container(color: Color.fromRGBO(255, 0, 0, 0.5))
Precache images and icons Link to heading
Flutter contains a function precacheImage() which can be used to reduce the loading time of images and icons. You can use it in the initState() or didChangeDependencies() methods to speed up image display, for example.
Dart
const List<CatImage> images = [
CatImage(width: 150, height: 150, caption: 'Watch out'),
CatImage(width: 150, height: 160, caption: 'Hmm'),
CatImage(width: 160, height: 150, caption: 'Whats up'),
CatImage(width: 140, height: 150, caption: 'Miaoo'),
CatImage(width: 130, height: 150, caption: 'Hey'),
CatImage(width: 155, height: 150, caption: 'Hello'),
];
@override
void didChangeDependencies() {
super.didChangeDependencies();
for (CatImage image in images) {
precacheImage(NetworkImage(image.url), context);
}
}
Reduce memory consumption of ListView Link to heading
A ListView has two properties (addRepaintBoundary and addAutomaticKeepAlives) that can lead to a high memory consumption in certain cases. They tell the ListView to not dispose of items which are not visible on the screen at the moment. In terms of performance, this is good because scrolling is fast. But the invisible items still occupy memory space. If you have a long list of images, this can lead to a problem. The solution is to set the mentioned properties to false (they are set to true by default).
Dart
ListView.builder(
addAutomaticKeepAlives: false,
addRepaintBoundaries: false,
…
);
Always use keys Link to heading
Every widget has a key constructor parameter and creates an element in the widget tree. A key allows us to reuse an element instead of creating a new one. You can either use ValueKeys or GlobalKeys. GlobalKeys can be tricky because there can never be multiple widgets with the same key in the widget tree. ValueKeys on the other hand will lead to bloaty code as you need to define them for each widget.
💡 Tip
Do you want more tips? Check out my free ebook!
Conclusion Link to heading
In this article, you learned how you can boost your Flutter app performance with these 6 tips.
Related articles Link to heading

A comparison of 6 JsonToDart tools for Flutter/Dart developers Link to heading
Instead of writing code yourself, you can always use generators to create Dart model classes from JSON. Here are the results of my evaluation of some free tools for you.

How to organize your Flutter app assets, styles, colors, images Link to heading
A growing app has a lot of resources included that are used in various places. With this approach, you’ll know where to put things and how to reference them.

Building a simple text translation app with Flutter and Firebase Link to heading
With Firebase Extensions you can build a simple text translation app that does most of the work for you.