CachedNetworkImage 是一个 Flutter 组件,用于从网络加载和缓存图片,支持进度、占位符和错误处理。根据 包的官方页面,该库基于 flutter_cache_manager,并提供具有可配置 TTL 的自动磁盘缓存。CachedNetworkImage 是在 Flutter 应用中带缓存加载图片的标准解决方案。
要点
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 使用双层缓存系统:ImageCache(内存)和 flutter_cache_manager(磁盘 + SQLite)。ImageCache 是解码后图片的全局缓存,有数量(默认为 1000)和大小(默认为 100 MB)限制。flutter_cache_manager 管理磁盘上的文件及其元数据。
当 CachedNetworkImage 收到图片请求时,它首先检查 Flutter 的 ImageCache — 如果图片已在内存中解码,则立即显示。如果未命中,则通过 flutter_cache_manager 检查磁盘:SQLite 查询检查文件是否存在于缓存中以及其 TTL 是否未过期。如果文件是最新的 — 从磁盘读取、解码并显示。如果文件不存在或 TTL 已过期 — 则执行 HTTP 请求。
DefaultCacheManager 提供 emptyCache()(完全清除)、cleanCache()(仅删除过期)和 clearCacheWithAge()(带自定义日期)方法。ImageCache 在内存压力下自动清除,或通过 imageCache.clear() 手动清除。
CachedNetworkImage 建立在标准 Flutter 组件的组合之上。内部实现使用 ImageProvider 进行异步加载,使用 StatefulWidget 跟踪生命周期。
imageUrl — 必需参数,图片的 URL(String 或 Uri)。placeholder — 加载期间显示的组件。errorWidget — 加载错误时显示的组件。progressIndicatorBuilder — 接收 context、URL 和带有 totalSize 和 downloadedSize 字段的 DownloadProgress 的构建器。
CachedNetworkImageProvider — ImageProvider 的实现,返回 CachedNetworkStreamImage,管理下载和缓存。该提供者与 Flutter ImageCache 集成,并支持标准 ImageProvider 的所有功能:缩放、居中和重复。
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 查询。
CachedNetworkImage 提供两种主要的加载方式:CachedNetworkImage 组件和用于自定义场景的 CachedNetworkImageProvider。
CachedNetworkImage — 主要方式。只需提供 imageUrl 和 placeholder。组件会自动显示占位符直到加载完成,然后将其替换为图片。
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。
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 — 用于 Image 或 DecorationImage 的提供者,无需使用 CachedNetworkImage 组件。在使用 BoxDecoration、FadeInImage 或自定义 Image 组件时很有用。
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: CachedNetworkImageProvider(
"https://example.com/bg.jpg",
maxWidthBytes: 2048,
maxHeightBytes: 2048,
),
fit: BoxFit.cover,
),
),
)
CachedNetworkImage 中的 imageBuilder 参数允许将标准 Image 组件替换为自定义实现。除了直接显示 Image,还可以使用带装饰的 Container、带裁剪的 ClipRRect 或带水波纹效果的 Ink.image。imageBuilder 接收上下文和准备好图片的 ImageProvider,完全控制渲染过程。
额外参数:memCacheWidth 和 memCacheHeight 限制 RAM 中缓存图片的大小,减少 Flutter ImageCache 的负载。cacheKey 允许设置自定义缓存键而不是 URL,这对于 URL 中包含授权令牌的图片很有用(查询参数每次请求都会改变,但内容保持不变)。
标准的 Image.network 组件在每次组件重建时加载图片,不保存到磁盘。CachedNetworkImage 添加了文件缓存、进度和错误处理,但也增加对 flutter_cache_manager 和 SQLite 的依赖。
| 标准 | Image.network | CachedNetworkImage |
|---|---|---|
| 磁盘缓存 | 无(仅 Flutter 内存缓存) | 有(SQLite + 文件) |
| 进度 | 无 | progressIndicatorBuilder |
| 错误组件 | 仅在调试模式中显示红色占位符 | 自定义 errorWidget |
| 缓存 TTL | 不适用 | 可配置(默认 7 天) |
| 依赖 | 无(内置于 Flutter) | cached_network_image + flutter_cache_manager + sqflite |
| 离线访问 | 无 | 有(对于之前下载过的文件) |
| 构建大小 | 额外 0 KB | 额外约 300 KB |
对于离线工作和节省带宽很重要的项目,CachedNetworkImage 是明确的选择。对于简单的临时屏幕(例如引导页或启动画面),Image.network 不需要额外的依赖。
CachedNetworkImage 作为标准 pub.dev 依赖添加。安装后,组件即可使用。flutter_cache_manager 作为传递性依赖引入。
// pubspec.yaml
dependencies:
flutter:
sdk: flutter
cached_network_image: ^3.4.1
默认使用 DefaultCacheManager,设置如下:TTL = 7 天,最大 200 个文件。要更改全局参数,请使用 Config 创建自定义 CacheManager 实例,在其中重写 maxAgeCacheObject、maxNrOfCacheObjects 和 repo。
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,
// ...
)
maxWidthBytes 和 maxHeightBytes — 用于限制缓存文件大小的可选参数。当原始图片大于所需的屏幕尺寸时,这对于节省磁盘空间很有用。
常见问题
CachedNetworkImage — 用于从网络加载图片并自动缓存到磁盘的 Flutter 组件。用于节省带宽、离线工作以及显示加载进度,这些在标准的 Image.network 中是不存在的。
在 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 天。
调用 DefaultCacheManager().emptyCache() 可完全清除所有文件。仅清除过期文件请使用 cleanCache()。自定义管理器通过在其实例上调用 emptyCache 来清除。
是的,CachedNetworkImage 支持 Android、iOS、Web、macOS、Windows 和 Linux。统一的 API 确保在所有平台上的相同行为,缓存通过为每个操作系统适配的 flutter_cache_manager 工作。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。