Flutter is a cross-platform framework that lets you create fast and beautiful app for mobile, web, and desktop. Flutter aims to provide 60 frames per second (fps) performance, or 120 fps performance on devices capable of 120Hz updates. However, sometimes your app might not run as smoothly as you expect, and you might encounter jank, stutter, or lag.

Jank occurs when the UI doesn’t render smoothly, and animations appear frozen. Every once in a while, a frame takes 10 times longer to render, so it is dropped. Jank can ruin the user experience and make your app look unprofessional.

How do you avoid jank and optimize your Flutter app’s performance? Where do you start? What tools can you use? In this article, we will explore some Hacks and best practices for Flutter performance optimization, based on the official documentation and other resources.

Hack 1: Run in profile mode on a real device

The first Hack for Flutter performance optimization is to run your app in profile mode on a real device. Profile mode is a special mode that runs your app with optimizations similar to release mode, but also enables some performance measurement tools. Profile mode helps you identify potential performance issues and measure the impact of your optimizations.

To run your app in profile mode, use the flutter run --profile command or select the profile option in your IDE. You can also use the flutter build --profile command to create a profile build for your app.

Running your app on an actual device is important because simulators and emulators don’t use the same hardware as real devices, which leads to differences in their performance. Compared to real devices, some simulator operations are faster, while others are slower. Also, debug mode enables additional checks (such as asserts) that don’t run in profile or release builds, and these checks can be expensive.

You should consider checking performance on the slowest device that your users might reasonably use. This way, you can ensure that your app runs smoothly on all devices.

Hack 2: Use the performance overlay and other tools

The second Hack for Flutter performance optimization is to use the performance overlay and other tools to diagnose performance problems. The performance overlay is a widget that displays two graphs on top of your app’s UI. The graphs show how much time each frame takes to render on the UI thread (top graph) and the raster thread (bottom graph). The raster thread was previously known as the GPU thread.

To enable the performance overlay, use the flutter run --profile --show-performance-overlay command or press P while running your app in profile mode. You can also enable it programmatically using the PerformanceOverlay widget or from the command line using the showPerformanceOverlay parameter.

The performance overlay helps you identify janky frames by showing spikes in the graphs. Ideally, each frame should take less than 16 ms to render for 60 fps performance. If a frame takes longer than 16 ms, it means that it missed the deadline and caused a jank.

You can also use other tools to analyze your app’s performance, such as:

Hack 3: Minimize expensive operations

The third Hack for Flutter performance optimization is to minimize expensive operations in your code. Expensive operations are those that consume a lot of resources, such as CPU, memory, or network. Some examples of expensive operations are:

Hack 4: Use lazy loading and pagination

The fourth Hack for Flutter performance optimization is to use lazy loading and pagination for your data. Lazy loading is a technique that loads data only when it is needed, instead of loading it all at once. Pagination is a technique that divides data into smaller chunks or pages and loads them one by one as the user scrolls.

Lazy loading and pagination can improve your app’s performance by reducing the amount of data that needs to be fetched from the network or the device storage, reducing the memory usage of your app, and reducing the UI complexity of your app.

To implement lazy loading and pagination in Flutter, you can use various widgets and plugins, such as:

Hack 5: Use tree shaking for your code

The fifth Hack for Flutter performance optimization is to use tree shaking for your code. Tree shaking is a technique that removes unused code from your app’s binary file, reducing its size and improving its startup time.

Tree shaking works by analyzing your code and determining which parts are reachable and which parts are not. Only the reachable parts are included in the final output, while the unreachable parts are discarded. This way, you can avoid shipping unnecessary code that never gets executed.

Tree shaking can be useful when you have large or optional features in your app that are not needed by all users. For example, you can use tree shaking for:

To enable tree shaking in Flutter, you don’t need to do anything special. Flutter automatically performs tree shaking when building your app in release mode. However, you can help tree shaking by following some best practices, such as:

Learn more about tree shaking in Flutter here.

Hack 6: Use deferred loading for your code

The sixth Hack for Flutter performance optimization is to use deferred loading for your code. Deferred loading (also called lazy loading) is a technique that allows you to load parts of your code on demand, instead of loading them all at once. This can reduce the initial download size and memory usage of your app, and improve its startup time.

To use deferred loading in Flutter, you need to use the deferred keyword after the import statement and specify an alias for the imported library. Then, you need to call the loadLibrary() method on the alias to load the library when you need it. For example:

// Import a library lazily

import 'package:foo/foo.dart' deferred as foo;

// Load the library when needed

await foo.loadLibrary();

// Use the library

foo.bar();

Deferred loading can be useful when you have large or optional features in your app that are not needed at startup or by all users. For example, you can use deferred loading for:

However, deferred loading also has some limitations and challenges, such as:

To learn more about deferred loading in Flutter, see Deferred Components in the official documentation.

That’s it!

I hope you enjoyed this article and learned something new. If you have any questions or feedback, feel free to leave a comment below.