CachedNetworkImage:是什么、核心概念及 ImageProvider 组件

作者: IT Sectr 发布日期: 2026-05-05 阅读时间: 8 分钟

CachedNetworkImage 是一个 Flutter 组件,用于从网络加载和缓存图片,支持进度、占位符和错误处理。根据 包的官方页面,该库基于 flutter_cache_manager,并提供具有可配置 TTL 的自动磁盘缓存。CachedNetworkImage 是在 Flutter 应用中带缓存加载图片的标准解决方案。

要点

  • CachedNetworkImage — 用于从网络加载和缓存图片并具有自动缓存管理的 Flutter 组件。
  • flutter_cache_manager — 实现双层缓存(文件 + 内存)并带有 SQLite 索引的基础包。
  • ImageProvider — Flutter 中用于从任何源异步获取解码后图片的机制。
  • 进度指示器 内置于组件中,通过 builder 参数 progressIndicatorBuilder 显示加载百分比。
  • 错误处理 — 组件在加载失败时显示 errorWidget,用替代图替换损坏的图片。

什么是 CachedNetworkImage?

CachedNetworkImage 是同名 pub.dev 包中的一个 Flutter 组件,提供从网络加载图片并自动缓存的功能。它是标准 Image.network 之上的一层,添加了文件缓存、进度指示器和自定义错误处理。

在内部,CachedNetworkImage 使用 flutter_cache_manager — 一个带有 SQLite 数据库用于跟踪文件的缓存管理器。在第一次请求时,图片从网络下载并保存到磁盘,在后续请求中,根据 TTL(默认为 7 天)从缓存中提供。内存中的缓存由 Flutter 的标准 ImageCache 管理。

该包在 pub.dev 上有超过 4,000 个赞,并用于数千个 Flutter 项目。CachedNetworkImage 支持所有 Flutter 平台:Android、iOS、Web、macOS、Windows 和 Linux。得益于统一的 API,开发者无需特定于平台的代码即可获得跨平台的图片加载。

Flutter 中的图片缓存如何工作

Flutter 使用双层缓存系统:ImageCache(内存)和 flutter_cache_manager(磁盘 + SQLite)。ImageCache 是解码后图片的全局缓存,有数量(默认为 1000)和大小(默认为 100 MB)限制。flutter_cache_manager 管理磁盘上的文件及其元数据。

检查顺序

当 CachedNetworkImage 收到图片请求时,它首先检查 Flutter 的 ImageCache — 如果图片已在内存中解码,则立即显示。如果未命中,则通过 flutter_cache_manager 检查磁盘:SQLite 查询检查文件是否存在于缓存中以及其 TTL 是否未过期。如果文件是最新的 — 从磁盘读取、解码并显示。如果文件不存在或 TTL 已过期 — 则执行 HTTP 请求。

  • ImageCache — Flutter 全局缓存,默认为 1000 个元素 / 100 MB
  • flutter_cache_manager — SQLite + 文件系统,TTL 7 天
  • HTTP 加载 — 通过 http 包或自定义 HttpClient 执行

清除缓存

DefaultCacheManager 提供 emptyCache()(完全清除)、cleanCache()(仅删除过期)和 clearCacheWithAge()(带自定义日期)方法。ImageCache 在内存压力下自动清除,或通过 imageCache.clear() 手动清除。

CachedNetworkImage 组件的架构

CachedNetworkImage 建立在标准 Flutter 组件的组合之上。内部实现使用 ImageProvider 进行异步加载,使用 StatefulWidget 跟踪生命周期。

关键参数

imageUrl — 必需参数,图片的 URL(String 或 Uri)。placeholder — 加载期间显示的组件。errorWidget — 加载错误时显示的组件。progressIndicatorBuilder — 接收 context、URL 和带有 totalSize 和 downloadedSize 字段的 DownloadProgress 的构建器。

ImageProvider

CachedNetworkImageProvider — ImageProvider 的实现,返回 CachedNetworkStreamImage,管理下载和缓存。该提供者与 Flutter ImageCache 集成,并支持标准 ImageProvider 的所有功能:缩放、居中和重复。

配置 flutter_cache_manager

flutter_cache_manager — 构成 CachedNetworkImage 缓存基础的库。它提供带有配置好的 SQLite 数据库、TTL 和文件限制的 DefaultCacheManager。如有需要,可以创建具有唯一参数的自定义 CacheManager。

参数描述默认值
maxAgeCacheObject文件的最长存储期限7 天
maxNrOfCacheObjects最大文件数量200
key管理器的唯一标识符“default”
repo元数据的存储类型CacheObjectRepository (SQLite)
fileService用于下载的 HTTP 客户端HttpFileService

自定义 CacheManager 通过继承 CacheManager 并重写方法来创建。当需要将图片存储在单独的目录中或使用不同的 HTTP 客户端时,这很有用。然后将管理器实例传递给 CachedNetworkImage 的 cacheManager 参数。

DefaultCacheManager 的 SQLite 数据库位于应用的 temporaryDirectory 目录中,路径为 `{key}/CacheObjects.db`。它包含 cacheObjects 表,字段包括 key(URL)、relativePath、url、creationDate、eTag、httpHeaders。清除过期记录时,使用基于 maxAgeCacheObject 的条件 SQL 查询。

在 Dart 中使用 CachedNetworkImage 的示例

CachedNetworkImage 提供两种主要的加载方式:CachedNetworkImage 组件和用于自定义场景的 CachedNetworkImageProvider。

带占位符的基本加载

CachedNetworkImage — 主要方式。只需提供 imageUrl 和 placeholder。组件会自动显示占位符直到加载完成,然后将其替换为图片。

dart
CachedNetworkImage(
    imageUrl: "https://example.com/photo.jpg",
    placeholder: (context, url) => CircularProgressIndicator(),
    errorWidget: (context, url, error) => Icon(Icons.error),
    width: 200,
    height: 200,
    fit: BoxFit.cover,
)

placeholder 和 errorWidget 是接收 context、URL 和(对于 errorWidget)错误对象的构建器函数。这种方法允许根据 URL 或错误类型显示不同的替代内容。

带进度的加载

progressIndicatorBuilder — 允许以百分比显示加载进度的参数。DownloadProgress 包含 totalSize(如果大小未知则可能为 -1)和 downloadedSize。

dart
CachedNetworkImage(
    imageUrl: "https://example.com/large.jpg",
    progressIndicatorBuilder: (context, url, downloadProgress) {
        return Center(
            child: SizedBox(
                width: 50,
                height: 50,
                child: Stack(
                    alignment: Alignment.center,
                    children: [
                        CircularProgressIndicator(
                            value: downloadProgress.progress,
                        ),
                        Text(
                            "\(downloadProgress.downloadedSize ~/ 1024) KB",
                        ),
                    ],
                ),
            ),
        };
    },
    imageBuilder: (context, imageProvider) {
        return Container(
            decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(12),
                image: DecorationImage(
                    image: imageProvider,
                    fit: BoxFit.cover,
                ),
            ),
        };
    },
)

imageBuilder — 可选参数,允许自定义图片显示:添加圆角、阴影、装饰。示例中使用带有 BorderRadius 的 DecorationImage 来实现圆角。

使用 CachedNetworkImageProvider

CachedNetworkImageProvider — 用于 Image 或 DecorationImage 的提供者,无需使用 CachedNetworkImage 组件。在使用 BoxDecoration、FadeInImage 或自定义 Image 组件时很有用。

dart
Container(
    decoration: BoxDecoration(
        image: DecorationImage(
            image: CachedNetworkImageProvider(
                "https://example.com/bg.jpg",
                maxWidthBytes: 2048,
                maxHeightBytes: 2048,
            ),
            fit: BoxFit.cover,
        ),
    ),
)

ImageBuilder 和自定义处理

CachedNetworkImage 中的 imageBuilder 参数允许将标准 Image 组件替换为自定义实现。除了直接显示 Image,还可以使用带装饰的 Container、带裁剪的 ClipRRect 或带水波纹效果的 Ink.image。imageBuilder 接收上下文和准备好图片的 ImageProvider,完全控制渲染过程。

额外参数:memCacheWidthmemCacheHeight 限制 RAM 中缓存图片的大小,减少 Flutter ImageCache 的负载。cacheKey 允许设置自定义缓存键而不是 URL,这对于 URL 中包含授权令牌的图片很有用(查询参数每次请求都会改变,但内容保持不变)。

CachedNetworkImage 与标准 Image.network 的比较

标准的 Image.network 组件在每次组件重建时加载图片,不保存到磁盘。CachedNetworkImage 添加了文件缓存、进度和错误处理,但也增加对 flutter_cache_manager 和 SQLite 的依赖。

标准Image.networkCachedNetworkImage
磁盘缓存无(仅 Flutter 内存缓存)有(SQLite + 文件)
进度progressIndicatorBuilder
错误组件仅在调试模式中显示红色占位符自定义 errorWidget
缓存 TTL不适用可配置(默认 7 天)
依赖无(内置于 Flutter)cached_network_image + flutter_cache_manager + sqflite
离线访问有(对于之前下载过的文件)
构建大小额外 0 KB额外约 300 KB

对于离线工作和节省带宽很重要的项目,CachedNetworkImage 是明确的选择。对于简单的临时屏幕(例如引导页或启动画面),Image.network 不需要额外的依赖。

在 Flutter 项目中设置 CachedNetworkImage

CachedNetworkImage 作为标准 pub.dev 依赖添加。安装后,组件即可使用。flutter_cache_manager 作为传递性依赖引入。

dart
// pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  cached_network_image: ^3.4.1

默认使用 DefaultCacheManager,设置如下:TTL = 7 天,最大 200 个文件。要更改全局参数,请使用 Config 创建自定义 CacheManager 实例,在其中重写 maxAgeCacheObject、maxNrOfCacheObjects 和 repo。

dart
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';

final customCacheManager = CacheManager(
  Config(
    "custom_images",
    stalePeriod: Duration(days: 14),
    maxNrOfCacheObjects: 500,
    repo: JsonCacheInfoRepository(
      databaseName: "custom_images_cache.db",
    ),
  ),
);

// 使用自定义管理器:
CachedNetworkImage(
    cacheManager: customCacheManager,
    imageUrl: url,
    // ...
)

maxWidthBytesmaxHeightBytes — 用于限制缓存文件大小的可选参数。当原始图片大于所需的屏幕尺寸时,这对于节省磁盘空间很有用。

常见问题

什么是 CachedNetworkImage,它有什么用?

CachedNetworkImage — 用于从网络加载图片并自动缓存到磁盘的 Flutter 组件。用于节省带宽、离线工作以及显示加载进度,这些在标准的 Image.network 中是不存在的。

如何将 CachedNetworkImage 添加到 Flutter 项目中?

在 pubspec.yaml 文件的 dependencies 部分添加 cached_network_image: ^3.4.1,然后运行 flutter pub get。之后在文件中导入包:import 'package:cached_network_image/cached_network_image.dart'。

如何更改缓存存储时间?

使用 Config 创建自定义 CacheManager,其中 stalePeriod 参数指定为 Duration。将创建的管理器传递给 CachedNetworkImage 组件的 cacheManager 参数。默认情况下,文件存储 7 天。

如何清除 CachedNetworkImage 的缓存?

调用 DefaultCacheManager().emptyCache() 可完全清除所有文件。仅清除过期文件请使用 cleanCache()。自定义管理器通过在其实例上调用 emptyCache 来清除。

CachedNetworkImage 是否在所有 Flutter 平台上工作?

是的,CachedNetworkImage 支持 Android、iOS、Web、macOS、Windows 和 Linux。统一的 API 确保在所有平台上的相同行为,缓存通过为每个操作系统适配的 flutter_cache_manager 工作。

总结

  • CachedNetworkImage — Flutter 中缓存加载图片的标准解决方案,在 pub.dev 上拥有超过 4,000 个赞。
  • 双层缓存(Flutter ImageCache + 通过 SQLite 的文件)最大限度地减少网络请求并加快显示速度。
  • progressIndicatorBuilder 允许为大图片和弱连接显示加载百分比。
  • 自定义 CacheManager 提供对 TTL、文件数量和存储路径的完全控制。
  • CachedNetworkImageProvider 与 DecorationImage 和 BoxDecoration 配合使用,扩展了使用场景。
  • 离线访问 之前下载的图片 — 与标准 Image.network 相比的关键优势。
  • 跨平台性 — 统一代码无需更改即可在所有六个 Flutter 平台上运行。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读