How to Cache Network Images in Flutter

Flutter Jun 16, 2023

Images are a crucial part of modern mobile applications, and efficiently loading and caching network images can greatly enhance the performance and user experience. In this post, we will explore how to cache network images in Flutter using the cached_network_image package. This package simplifies the process of fetching, displaying, and caching images from the network effortlessly.

1. Getting started

To get started we set up a basic Flutter application in main.dart that displays a NetworkImage.

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Cached Network Image Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Cached Network Image Example'),
        ),
        body: Center(
          child: Image.network(
              'https://picsum.photos/id/525/350/250'
          ),
        ),
      ),
    );
  }
}

We define a MyApp widget as our root widget, which extends StatelessWidget. Inside the build method, we create a MaterialApp as the main application container. The MaterialApp contains a Scaffold with an AppBar and a Center widget. Inside the Center widget, we display a NetworkImage using Image.network and provide the image URL (https://picsum.photos/id/525/350/250).

The picsum.photos website is a placeholder image generator that provides random images with various dimensions. By specifying the ID 525, we retrieve a specific image with a width of 350 pixels and a height of 250 pixels.

flutter_showing_network_image

2. Caching our Network Image

To begin, we need to add the cached_network_image package to our Flutter project. Execute the following command to install the package: flutter pub add cached_network_image.

After executing the command, let us make sure that we have the package. Open the pubspec.yaml file to check if you see the cached_network_image underneath the dependencies section:

dependencies:
  cached_network_image: ^3.2.3
  flutter:
    sdk: flutter

Now that we have the package let us use the CachedNetworkImage widget to load and cache network images. Replace the existing Image.network widget with the CachedNetworkImage widget in your code. See the example:

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Cached Network Image Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Cached Network Image Example'),
        ),
        body: Center(
          child: CachedNetworkImage(
              imageUrl: 'https://picsum.photos/id/525/350/250',
          ),
        ),
      ),
    );
  }
}

We import the cached_network_image package. After importing the package, we replace the Image.network widget with CachedNetworkImage. The CachedNetworkImage widget takes an imageUrl parameter, specifying the URL of the image to be fetched and cached.

flutter_showing_cached_network_image_with_fade_animation

As you can see the CachedNetworkImage provides a fade in animation.

3. Improving our CachedNetworkImage

The CachedNetworkImage offers convenient properties that can help us improve the user experience. For example, when the image is being loaded we can show a CircularProgressIndicator. Or if the image cannot be found we can show an Icon widget:

CachedNetworkImage(
  imageUrl: 'https://picsum.photos/id/525/350/250',
  placeholder: (context, url) => const CircularProgressIndicator(),
  errorWidget: (context, url, error) => const Icon(
    Icons.no_photography_outlined,
    size: 120,
  ),
),

We enhance the CachedNetworkImage widget by providing two additional properties: placeholder and errorWidget.

The placeholder property allows us to specify a widget that will be displayed while the image is being loaded. In the given example, we use a CircularProgressIndicator widget as the placeholder, which shows a loading spinner. This gives users visual feedback that the image is being fetched and helps improve the user experience.

flutter_showing_cached_network_image_with_loading_indicator

On the other hand, the errorWidget property allows us to specify a widget that will be displayed if the image fails to load or encounters an error. In the provided code snippet, we use an Icon widget with the Icons.no_photography_outlined icon, indicating that the image could not be found. Additionally, we set the size of the icon to 120 for better visibility.

flutter_showing_cached_network_image_error_widget

These properties, placeholder and errorWidget, give us the flexibility to customize the appearance and behavior of the CachedNetworkImage widget during the different stages of image loading. By providing user-friendly placeholders and error indicators, we can provide a smoother and more informative experience to users while network images are being fetched or encountering errors.

4. Comparison

After implementing the CachedNetworkImage, let us compare its performance with the NetworkImage. In our application, we observe the following:

flutter_initial_loading_of_cached_and_normal_network_image

Initial loading: Both CachedNetworkImage and NetworkImage have similar loading times initially.

flutter_subsequent _loading_of_cached_and_normal_network_image

Subsequent loading: However, the true power of CachedNetworkImage is evident when we reload the images. The CachedNetworkImage loads instantly from the cache, while the NetworkImage needs to fetch the image again from the URL.

5. Conclusion

Caching network images in Flutter using the cached_network_image package is crucial for better performance and user experience. It optimizes image loading, reduces bandwidth usage, and provides a smoother experience for users.

Tags