Optimize Flutter Performance: Handle Heavy Image with Ease
Recently, I came across a property in Flutter: debugInvertOversizedImages.
You might think, What does it do? Okay, let me answer you. This property takes a boolean value, i.e., true or false; by default, it is false. If we make it true, then it will invert color and flip the images that are larger than their display size. With the help of this property, developers can easily stop oversized images on their app.
How do I enable the debugInvertOversizedImages property?
Go to your main.dart file. Inside the main method, add this line: debugInvertOversizedImages = true;
Note: Do not release the app with the debugInvertOversizedImages property enabled.
I have added a high-resolution image to my assets, and below is my demo implementation.
Now run your app. You can see all the oversized images being color-inverted and flipped by Flutter. Something similar to the screenshot below:
And if you check your logs, then you might see something like this:
Here, we are trying to load an image of 3688×4917, but actually, the display size is 1080×1493. And on the second line, we can see the solutions too.
Let’s try the first solution by adding the cacheHeight and cacheWidth parameters to the Image widget with the recommended dimensions provided by Flutter on the console. And your code should be similar to this.
Voilà, now your image will be displayed perfectly fine.
Now, let’s try with ResizeImage.
Before that, let’s learn what ResizeImage is.
Flutter’s ResizeImage class allows you to specify the desired dimensions at which images are decoded and cached instead of their full dimensions without altering the original image file. By resizing images to appropriate dimensions, we can significantly reduce memory usage and improve image loading time.
Now replace Image.asset with AssetImage, as ResizeImage takes image providers only. And set width and height to the same values we have added previously. We cannot display ResizeImage directly, so let’s wrap it in the Image widget. Your implementation should look something like this.
If both do the same thing, then what’s the difference? You might be wondering.
The ‘cacheWidth’ and ‘cacheHeight’ parameters of Image.asset are used for static resizing images before loading into the UI and remain the same for the whole lifetime of the app. The ResizeImage class is used for dynamic resizing of images at runtime and is generated every time the ImageProvide is used.
If you ask for my recommendation, I recommend you use the former one. Yes, cacheWidth’ and ‘cacheHeight’ parameters of the Image widget. This can be used on Image.assets, Image.network, Image.file, and Image.memory.
What if you are using the cache_networked_image package instead of Image.network?
You can pass your desired dimension value to the memCacheHeight and memCacheWidth properties of the CachedNetworkImage class. If you are using the CachedNetworkImageProvider class, then you don’t have access to these properties. Instead, you should wrap it under ResizeImage.
Bonus: Dynamically determining image cache size by Extensions and MediaQuery class.
The usage of ImageExtension is pretty simple.
Conclusion:
In this article, we explored how to load heavy images efficiently and optimize performance when displaying heavy images from assets and networks.