Take your Flutter App performance to next level - Part: 1

Cavin Macwan
7Span
Published in
6 min readDec 14, 2022

Generally, Flutter applications are performed by default, so you just need to avoid common mistakes to get excellent performance. These best practices will help you to write the most effective Flutter app possible.

So without further a do let’s get started.

1. Use nil package

Whenever we want to display or return nothing to the screen, we use Container or SizedBox for that. But what happens behind the scenes is that the two widgets create a Render Object that is not visible on the screen, but still takes memory.

This package creates an element and it does not create render objects. Therefore, by using this package, it will allow you to avoid the creation of useless rendering objects. This will save some memory and it will increase performance.

Below is an example of how to use it :

Use case of nil package

Instead of returning nil, you can also return const Nil().

Note : There is one thing to keep in mind though. This package creates just an element and not a Render object, therefore you should not use nil in Column or ListView, you can use Sizedbox.shrink() if you want to use it inside Column or ListView.

2. Use const / static

You have seen a lot of times that you should always use the const keyword where possible. But why is that?

Imagine the following scenario. We have a function named doSomething and in that function, we are running a simple for loop 100 times and in that loop, we are creating 2 objects of a class.

Notice that the ConstObject class’s constructor is marked as const while the other class ConstObjectNot class’s constructor is not marked as const.

Example of using the const keyword

Now if we run this in our app, the constobject’s object will create only once even if the loop was running 100 times but the notConstobject will create its instance 100 times because we did not use the const keyword there.

Therefore making a widget as const means it will only be created once in its lifetime. Therefore it will save you a lot of memory and it will boost your app’s performance. The widget will not change even when we call setstate.

This doesn’t just apply to a Widget but it can apply to any Object in Flutter.

But sometimes we can’t make an variable/function as const so in those situations you can do make use of static keyword for non-constant objects. The function or variable marked as constant will only be created for only once therefore it will save you some memory when you can’t use const.

Example: Suppose you want to create a file for rest API in dart and it has all the get, post, put and delete methods. So the instance of that class should be only one in the entire app. Therefore you can mark those methods as static.

3. Delay execution when possible

Consider the following code:

Example of delaying the execution
Example of delaying the execution
  • Firstly we are creating 3 variables and 2 of them are late-type variables.
  • Then in the doSomething() function, we are checking 3 conditions.
  • We only want to check for operation1 if the first condition is true. Therefore by making the operation1 and operation2 late type of variables, they will be only computed if the first condition is true
  • Therefore it will save you some computation cost.

If you don’t know about the late keyword, it essentially means that it will be only initialized whenever we access it.

4. Use Stateless/Stateful widgets over functions

Consider these 2 code snippets :

padding example using function
Returning widget in function
Example of extracting as a widget
Making a Stateless widget

When we have a large layout, then what we usually do is split using methods for each widget. But whenever we extract a widget as a method it is considered to be a pretty bad pattern(anti-pattern) because of the following reasons:

  1. If you are in a Stateful Widget and the set state is triggered, then it will also refresh the widgets that we have within the method, which leads us to waste CPU cycles.
  2. If you see the widget tree in dart developer tools, you can notice that you can’t distinguish between your extracted method.

Therefore always extract in Stateless / Stateful Widget instead of returning them in methods.

5. Avoid rebuilding unnecessary widgets inside AnimatedBuilder

Whenever you want to use AnimatedBuilder for your animations, always add your widget in the child parameter as shown below:

  • Don’t do it like this :
Bad use of animated builder
  • Instead, use it like this :
Good use of animated builder

We used the child attribute provided by the AnimatedBuilder, which allows us to cache widgets to reuse them in our animation.

We do this because that widget is not going to change, the only thing it will do is rotate, but for that, we have the Transform widget.

6. Precache your images

Whenever you load a picture from assets to your Flutter App, sometimes it takes a bit of time to load, But by precaching the images in your memory the images will load as quickly as possible.

Below is the code snippet for preaching your images:

Example of Precaching the image

Note: precacheImage method is provided by flutter, if you want to cache SVG, then you can use precache method of the flutter_svg package.

7. Don’t use ClipRRect / Opacity widget when not nessecarry

You might be thinking that using ClipRRect or Opacity won’t slow down your App, But to show the difference between using ClipRRect / Opacity we are gonna do the following :

  1. Consider the following code :
Bad use of ClipRRect vs good use of ClipRRect

Now run the first code in Profile Mode and in the terminal type this command:

flutter screenshot — type=skia — observatory-url=[url]

This will create a skia screenshot in your root of your application directory. Now go to this site and paste the skia screenshot into it. It will show something like this.

  • You can see that the save method is calling multiple times here which is a lot expensive in terms of memory and computing (refer 1.0)
1.0 Bad use of ClipRRect
  • Whereas in the second example, we are still giving border-radius but instead of using ClipRRect, we are using BoxDecoration of Container which is not that much expensive.
  • We can also see that the save layer is called only twice.
2.0 Good use of ClipRRect

Here’s another example of using the Opacity widget :

Bad use of Opacity vs Good use of Opacity
  • As you can see, instead of wrapping a widget with Opacity, we can directly give an opacity to color which is more performance optimized since it will not call the save layer function over and over again.
  • You can try to capture the skia screenshot of it and trying out in skia debugger to see the details of it.
  • Below are the links for further reading till the second part gets released:

https://www.youtube.com/watch?v=KH-3tbD7NoU&t=1s

Thanks for reading this article ❤️

I am open to flutter discussion and any questions.

Let’s be friends: LinkedIn Twitter

--

--

Cavin Macwan
7Span
Writer for

Passionate mobile developer. One thing I like more than learning new things: sharing them #FlutterDev| Developer @7Span | Contributor