The goodness of caching network images in a Flutter application does more than just boot up the performance of the application itself. Other significant benefits are:
- Reduce the burden on your server and reduce the cost you have to pay for bandwidth in loading images.
- Reduce internet charges for your users if they use 3G/4G/5G.
Fortunately, implementing image caching in Flutter is not an advanced task, and we can get it done with a few dozen lines of code and the help of a great plugin named cached_network_image.
Table of Contents
Overview
1. The cached_network_image plugin provides a widget named CachedNetworkImage that shows a network image with caching functionality. The image displayed with this widget will be downloaded and stored in the cache directory of the app for a period of time. It will be available for offline use without an internet connection.
You can implement the widget as shown below:
CachedNetworkImage(
width: double.infinity,
height: 250,
fit: BoxFit.cover,
imageUrl: [image url],
progressIndicatorBuilder: (context, url, downloadProgress) =>
CircularProgressIndicator(value: downloadProgress.progress),
errorWidget: (context, url, error) => Icon(
Icons.error,
size: 100,
color: Colors.red,
),
),
2. To delete the cached image, you can call the CachedNetworkImage.evictFromCache static method:
CachedNetworkImage.evictFromCache([image url])
Example
App Preview
The demo app we are going to build contains 2 images and a button. The first image will be cached, and the second one won’t. Here’s how it works:
- In the beginning, both images are loaded correctly because my wifi is ON.
- When I turn off my internet connection and restart the app, the first image is still fine, but the second one goes into error.
- When I press the button Remove Cached Images and restart the app, the first image will be replaced by an error icon. This behavior makes sense because the cached file is now gone.
- I enable my wifi again and restart the app. Everything is fine again.
This GIF depicts what I mean:
The Code
1. Install the cached_network_image plugin by running:
flutter pub add cached_network_image
2. The final code in lib/main.dart with explanations:
// main.dart
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: 'Kindacode.com',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const HomePage());
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// This image will be cached
final _image1 =
'https://www.kindacode.com/wp-content/uploads/2021/08/face.png';
// This image will not be cached
// It is added to show the difference
final _image2 =
'https://www.kindacode.com/wp-content/uploads/2021/08/cat.jpeg';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Kindacode.com'),
),
body: Padding(
padding: const EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Display image with caching
const Text('Caching'),
const SizedBox(
height: 10,
),
CachedNetworkImage(
width: double.infinity,
height: 250,
fit: BoxFit.cover,
imageUrl: _image1,
progressIndicatorBuilder: (context, url, downloadProgress) =>
CircularProgressIndicator(value: downloadProgress.progress),
errorWidget: (context, url, error) => const Icon(
Icons.error,
size: 100,
color: Colors.red,
),
),
const SizedBox(
height: 10,
),
// This button is used to remove the saved image from the cache directory
ElevatedButton(
onPressed: () {
CachedNetworkImage.evictFromCache(_image1);
},
child: const Text('Remove Cached Images')),
const SizedBox(
height: 10,
),
// Display image without caching
const Divider(),
const Text('Non Caching:'),
const SizedBox(
height: 10,
),
Image.network(
_image2,
width: double.infinity,
height: 200,
fit: BoxFit.cover,
)
],
),
),
);
}
}
Conclusion
We’ve examined a complete example of implementing image caching in a mobile application. This functionality provides a bunch of benefits at a low cost of time and effort (and money, as well). If you’d like to explore more new and interesting stuff in Flutter development, take a look at the following articles:
- Flutter & SQLite: CRUD Example
- Flutter + Firebase Storage: Upload, Retrieve, and Delete files
- Flutter image loading builder example
- Example of using ErrorWidget in Flutter
- How to create a Filter/Search ListView in Flutter
- Flutter StreamBuilder examples (null safety)
You can also take a tour around our Flutter topic page and Dart topic page to see the latest tutorials and examples.