Skip to main content

Command Palette

Search for a command to run...

Simplify image caching in Flutter with this package

Updated
3 min read
Simplify image caching in Flutter with this package
D

I am a software developer specialized in mobile apps. About a decade ago I started my career as a web developer, but I soon moved into Android native development; however for the last few years I've been building hybrid apps with Flutter. I consider myself a passionate programmer, I enjoy writing clean and scalable code. In addition to developing apps, I also have knowledge of backend services development, web development, installation and maintenance of servers, marketing applied to the growth of web applications... among other things. I also like to create video games in my free time and write about topics that interest me in the technology world: the last tech trends, experiments that I do, and topics regarding user privacy. You can find more about me, my articles and my projects on my website: davidserrano.io

If your application showcases one or more images that are hosted on an internet server, it is generally wise to cache these images temporarily. This will prevent the need to repeatedly download them as the user navigates through your application.

For instance, consider a social network where users can browse their news feed, view post details, and save posts as favorites. Now, let's consider the implications of having to download the same image repeatedly. If the user had to download the thumbnail every time they scrolled through the post list, accessed post details, or viewed their favorites list, it would result in unnecessary network resource usage and server overload. Moreover, the user would have to wait for the image to download each time, leading to a frustrating experience.

📽 Video version available on YouTube and Odysee

For this reason, Flutter has a built-in mechanism that enables the management of files in a specific directory designed for temporary files. The primary purpose of this directory is to store temporary data, which can be regenerated by the application if they are deleted. The goal of this directory is to improve the overall performance or to enhance the user experience in some way. Nevertheless, managing these files can be dull and tedious. To simplify this process, we have the cached_network_image package, which abstracts us from cache memory management.

This package will take care of downloading the image the first time, saving it in the cache, and will retrieve it from there if the same image is requested again.

How to cache an Image from a URL in Flutter

Let's create a sample application to see how it works:

flutter create cached_network_image_sample

Now let's install cached_network_image:

flutter pub add cached_network_image

As an example, I will take a real photo of the galaxy. This photo is quite large, replace the contents of lib/main.dart with the following:

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const App());
}

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'cached_network_image sample',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MainScreen(),
    );
  }
}

class MainScreen extends StatelessWidget {
  static const _url = 'https://cdn.eso.org/images/large/eso1031b.jpg';

  const MainScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('cached_network_image sample'),
      ),
      body: Center(
        child: Container(
          padding: const EdgeInsets.only(
            left: 24.0,
            right: 24.0,
          ),
          child: CachedNetworkImage(
            imageUrl: _url,
          ),
        ),
      ),
    );
  }
}

The first time CachedNetworkImage requests to render this image it will download it from the internet and save it, and from then on it will retrieve it from the cache. We can also set a specific loading widget via the progressIndicatorBuilder parameter:

// [...]
child: CachedNetworkImage(
  imageUrl: _url,
  progressIndicatorBuilder: (context, url, progress) =>
      const CircularProgressIndicator(),
),
// [...]

It is also possible to define a widget that will be displayed in case the image load fails for any reason:

child: CachedNetworkImage(
  imageUrl: _url,
  progressIndicatorBuilder: (context, url, progress) =>
  const CircularProgressIndicator(),
  errorWidget: (context, url, error) => const Center(
    child: Icon(
      Icons.error,
      color: Colors.red,
    ),
  ),
),

Try to alter the URL of the image to break it, you will see that the indicated widget is displayed instead.

As you can see, this easy-to-use package eliminates the need to store images downloaded from the internet, thus enhancing the usability and experience of our application.

I hope this article has been useful to you, see you in the next one.

Happy coding!

More from this blog

David Serrano

70 posts

I'm a mobile developer and an entrepreneur. In this blog you will find articles, tutorials and tricks to design, build and grow your mobile apps.