【开源鸿蒙跨平台开发训练营】Flutter框架开发鸿蒙应用的图片缓存与占位图优化

目前项目主要是网络图片的加载,发现每次图片都存在重复多次的情况,体验上有问题,现在下手看看如何优化。

文章目录

优化图片缓存与占位图

这里讨论的是与图片相关的性能优化实现:网络图片内存缓存 (单例 Dio + LRU)、加载中/失败占位图,以及与设置页「清除缓存」的联动。


一、目标与方案

  • 目标
    1. 同一图片 URL 只下载一次,避免重复请求与流量浪费。
    2. 使用单例 Dio 做图片请求,减少连接数、提升 HarmonyOS 等平台稳定性。
    3. 加载中与加载失败时展示统一、可定制的占位图,提升体验。
    4. 设置页「清除缓存」同时清除本应用的图片内存缓存。
  • 方案
    • 新增 图片缓存服务ImageCacheService):单例 Dio + 内存 LRU 缓存(最多 80 张),请求去重(同一 URL 并发只发一次)。
    • NetworkImageWidget 改为通过 ImageCacheService 取图;支持可选 placeholder(加载中)、errorPlaceholder(失败);未传时使用资源图片 asset/image/placeholder.pngasset/image/errorPlaceholder.png 作为默认占位图。
    • CacheService 在清除 Flutter ImageCache 时同时调用 ImageCacheService().clearMemoryCache()

二、涉及文件

文件 说明
lib/services/image_cache_service.dart 新增。图片缓存服务:单例 Dio、LRU 内存缓存、请求去重、清除接口。
lib/widgets/network_image_widget.dart 重构 。使用缓存服务取图;新增 placeholder / errorPlaceholder;默认占位使用资源图片。
lib/services/cache_service.dart 清除缓存时增加 ImageCacheService().clearMemoryCache()
pubspec.yaml 注册资源:asset/image/placeholder.pngasset/image/errorPlaceholder.png
asset/image/placeholder.png 加载中占位图资源。
asset/image/errorPlaceholder.png 加载失败占位图资源(如「无法加载图片」图示)。

三、实现说明

3.1 ImageCacheService(图片缓存服务)

  • 单例 Dio:构造时创建一次,所有图片请求共用,统一超时与 UA(HarmonyOS 兼容)。
  • 内存缓存Map<String, Uint8List> + List<String> 做 LRU;最多保留 _maxCacheCount = 80 条,超出时淘汰最久未访问的 URL。
  • 请求去重Map<String, Future<Uint8List?>> _inFlight;同一 URL 多次调用 getImage 时共用一个 Future,避免重复下载。
  • 接口
    • getImage(String url):先查缓存 → 再查进行中请求 → 否则发起下载并写入缓存。
    • clearMemoryCache():清空 _cache_lruKeys,供设置页「清除缓存」使用。

3.2 NetworkImageWidget(网络图片组件)

  • 数据来源ImageCacheService().getImage(imageUrl),不再为每张图新建 Dio。
  • 占位图
    • 加载中placeholder 为 null 时使用资源 asset/image/placeholder.png,与主图一致使用 fit 填充。
    • 加载失败errorPlaceholder 为 null 时使用资源 asset/image/errorPlaceholder.png(如「无法加载图片」图示),与主图一致使用 fit 填充。
    • 调用方可通过 placeholder / errorPlaceholder 传入自定义 Widget,覆盖默认资源图。
  • 生命周期didUpdateWidget 中若 imageUrl 变化则重新加载;dispose 前通过 _disposed 避免异步回调中 setState
  • 移除 :原每图 print 日志已去掉,减少生产环境开销。

3.3 CacheService(清除缓存)

  • clearImageCache() 在原有 PaintingBinding.instance.imageCacheclear / clearLiveImages 之后,增加 ImageCacheService().clearMemoryCache(),保证设置页「清除缓存」会一并清掉应用内图片内存缓存。

四、使用方式

准备 placeholder.pngerrorPlaceholder.png 素材,引入到

复制代码
/asset/image/errorPlaceholder.png
/asset/image/placeholder.png
dart 复制代码
NetworkImageWidget(
  imageUrl: imageUrl,
  fit: BoxFit.cover,
  placeholder: Container(
    color: Colors.grey[800],
    child: Center(child: CircularProgressIndicator(color: Colors.white)),
  ),
  errorPlaceholder: Container(
    color: Colors.grey[800],
    child: Center(child: Text('图片加载失败', style: TextStyle(color: Colors.white70))),
  ),
)

首页、发现页、收藏页、详情页中已有的 NetworkImageWidget 均无需改参数即可获得缓存与默认占位图;若需统一为自定义占位图,可在各页传入相同 placeholder / errorPlaceholder


五、效果与注意点

  • 效果
    • 同一 URL 只下载一次,列表/详情来回切换时图片从内存缓存读取,加载更快、流量更省。
    • 单例 Dio 减少连接数,有利于弱网与 HarmonyOS 环境。
    • 加载中/失败有统一占位,避免空白或杂乱布局。
  • 注意
    • 缓存仅内存、不落盘,进程退出后重新下载;缓存条数 80,可根据真机内存情况在 ImageCacheService._maxCacheCount 调整。
    • 设置页「清除缓存」会清空该 LRU 缓存与 Flutter 图片缓存,下次进入列表会重新拉取图片。

结束语

感谢阅读本帖,如对贴中内容有意见和建议的,欢迎与我联系交流,也欢迎加入开源鸿蒙跨平台社区:

https://openharmonycrossplatform.csdn.net

相关推荐
明君879976 分钟前
说说我为什么放弃使用 GetX,转而使用 flutter_bloc + GetIt
前端·flutter
程序员老刘2 小时前
Flutter版本选择指南:3.41开始进入稳定区间 | 2026年3月
flutter·ai编程·客户端
DJ斯特拉2 小时前
黑马点评技术汇总(四)缓存雪崩 && 缓存击穿
数据库·缓存
王码码20352 小时前
Flutter 三方库 sparky 的鸿蒙化适配指南 - 实现极简 2D 游戏引擎功能、支持高效精灵图渲染与跨端游戏逻辑
flutter·harmonyos·鸿蒙·openharmony
IAtlantiscsdn3 小时前
Redis面试题总结
数据库·redis·缓存
恋猫de小郭4 小时前
Android 17 新适配要求,各大权限进一步收紧,适配难度提升
android·前端·flutter
tangweiguo030519874 小时前
Flutter SSE 流式接收完全指南:从原理到实战
flutter
西西学代码6 小时前
Flutter---文件存储
flutter
林九生6 小时前
【Flutter】Flutter 拍照/相册选择后无法显示对话框问题解决方案
前端·javascript·flutter
●VON7 小时前
Flutter组件通信详解:父子组件交互的最佳实践
javascript·flutter·华为·交互·harmonyos·von