How to Cache Network Images in Flutter
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.

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.

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.

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.

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:

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

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.