5 Common Flutter Performance Mistakes and How to Fix Them

By flutter-performance-mistakes-and-fixes · October 29, 2026

5 Common Flutter Performance Mistakes and How to Fix Them

Flutter is fast by default, but a few common habits can make an app stutter, especially on mid-range phones. Here are five mistakes that cause most performance problems, with a fix for each. Always measure before and after, using the steps at the end.

1. Rebuilding too much of the widget tree

Calling setState on a large parent widget rebuilds everything beneath it, even parts that did not change.

Problem:

class ProductPage extends StatefulWidget {
  @override
  State<ProductPage> createState() => _ProductPageState();
}

class _ProductPageState extends State<ProductPage> {
  int quantity = 1;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        HeavyProductGallery(),   // rebuilds on every tap
        Text('Qty: $quantity'),
        ElevatedButton(
          onPressed: () => setState(() => quantity++),
          child: const Text('Add'),
        ),
      ],
    );
  }
}

Fix: move the changing part into its own small widget, so only that part rebuilds.

class QuantitySelector extends StatefulWidget {
  const QuantitySelector({super.key});
  @override
  State<QuantitySelector> createState() => _QuantitySelectorState();
}

class _QuantitySelectorState extends State<QuantitySelector> {
  int quantity = 1;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Text('Qty: $quantity'),
        ElevatedButton(
          onPressed: () => setState(() => quantity++),
          child: const Text('Add'),
        ),
      ],
    );
  }
}

The same idea applies with state management tools. Use selectors or scoped consumers so widgets listen only to the data they need.

2. Forgetting const constructors

A const widget is created once at compile time and Flutter can skip rebuilding it.

// Better
const Padding(
  padding: EdgeInsets.all(16),
  child: Text('Welcome'),
)

Turn on the prefer_const_constructors lint rule so the analyzer reminds you.

3. Building long lists the wrong way

Putting hundreds of items in a Column inside a SingleChildScrollView builds every item at once.

Fix: use ListView.builder, which builds only the items that are on screen.

ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(title: Text(items[index].name));
  },
)

Avoid shrinkWrap: true on large lists, because it forces Flutter to measure all the children.

4. Doing heavy work on the UI thread

Parsing a large JSON file, processing images, or running complex calculations inside the main isolate blocks frames and freezes the UI.

Fix: move the work to another isolate.

final result = await Isolate.run(() => parseLargeJson(rawText));

On older Flutter versions, compute() does the same job. Network and disk calls that are already asynchronous do not block the UI, but the CPU-heavy work after them can.

5. Loading images larger than needed

Decoding a 4000-pixel photo to show it in a 100-pixel thumbnail wastes memory and time.

Image.network(
  url,
  cacheWidth: 300,   // decode at roughly the displayed size
  fit: BoxFit.cover,
)

For network images, use a caching package, and serve appropriately sized images from your backend. Also avoid expensive effects like many nested Opacity, ClipRRect, or BackdropFilter widgets in scrolling lists, because they can trigger costly offscreen rendering.

How to measure properly

  1. Run in profile mode on a real device: flutter run --profile. Debug mode is much slower and misleading.
  2. Open Flutter DevTools and use the Performance view to find frames that take longer than about 16 ms (for a 60 Hz screen).
  3. Use the widget rebuild tracker to see which widgets rebuild too often.
  4. Test on a low-end phone. If it feels smooth there, it will feel smooth everywhere.

Quick checklist

  • Keep setState as local as possible
  • Add const wherever you can
  • Use ListView.builder for long lists
  • Move heavy computation to an isolate
  • Size images to how they are displayed
  • Profile in profile mode, not debug mode

Fixing these five issues solves most performance complaints in real apps. [Add a real before/after DevTools screenshot from one of your own apps here.]

Have an app idea worth building properly?

Tell us what you're building and we'll reply with next steps within a couple of days.