Flutter's built in Image widget is great, but there will be times when you need to pull images from the network, and will need to do that often. Doing many repeat queries for the same images can be a drain on network resources. In order to alleviate this potential issue, we can adopt a mechanism used by web browsers, caching. The built in widget does not offer this, but there is a nice package that's freely available on pub.dev that can do this for us, today, we'll look at cached_network_image.

To install the package, we can create a new empty project in VSCode, and in a new terminal window run the following command:

flutter pub add cached_network_image

Once the command finishes, your pubspec.yaml file should have a new dependency:

dependencies:
  cached_network_image: ^3.3.1

To use it, we'll need to import the package into our project's main.dart file.

import 'package:cached_network_image/cached_network_image.dart';

Now, we need a large image to test with, I found this image using Bing.

The image is a big image, over 1mb, which is big enough to be problematic if the end user's internet connection is poor, and having to pull an image like this every time the app is used can be a drain on time and resources. Let's go ahead and take a look at how to use the widget:

CachedNetworkImage(
  imageUrl: bigImageUrl,
),

Compare this to the normal Image widget:

Image.network(
  bigImageUrl,
),

The difference doesn't look dramatic, but let's replace the main.dart file in our project with the contents below:

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

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

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

  @override
  Widget build(BuildContext context) {
    String bigImageUrl =
        "https://th.bing.com/th/id/R.5d0ad77c8c5547b7f15e1ed6c62c84bf?rik=oLS0es8LtTgtng&riu=http%3a%2f%2fwww.mauvecloud.net%2fimages%2fplasma.gif&ehk=DCP6WmJPAxk5kBcX6LoaTHGX%2b8zXmsqa9xVKKbO9ZUc%3d&risl=&pid=ImgRaw&r=0";
    String badUrl =
        "https://th.bing.com/th/id/R.5d0ad77c8c5547b7f15e1ed6c62c84bf?rik=oLS0es8LtTgtng&riu=http%3a%2f%2fwww.mauvecloud.net%2fimages%2fplasma.gif&ehk=DCP6WmJPAxk5kBcX6LoaTHGX%2b8zXmsq";

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text("Cached Network Image"),
          backgroundColor: Colors.blue,
          foregroundColor: Colors.white,
        ),
        body: Column(
          children: [
            //
            // Image (Regular)
            //
            Expanded(
              child: Stack(
                alignment: Alignment.center,
                children: [
                  Image.network(
                    bigImageUrl,
                  ),
                  const Center(
                    child: Text(
                      "Network Image",
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
                ],
              ),
            ),
            //
            // Image (Cached)
            //
            const SizedBox(height: 20),
            Expanded(
              child: Stack(
                alignment: Alignment.center,
                children: [
                  CachedNetworkImage(
                    imageUrl: bigImageUrl,
                  ),
                  const Center(
                    child: Text(
                      "Cached Network Image",
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}