【开源鸿蒙跨平台开发训练营】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

相关推荐
微祎_9 小时前
Flutter for OpenHarmony:链迹 - 基于Flutter的会话级快速链接板极简实现方案
flutter
微祎_9 小时前
Flutter for OpenHarmony:魔方计时器开发实战 - 基于Flutter的专业番茄工作法应用实现与交互设计
flutter·交互
程序猿阿伟10 小时前
《GraphQL批处理与全局缓存共享的底层逻辑》
后端·缓存·graphql
学到头秃的suhian11 小时前
Redis缓存
数据库·redis·缓存
苏渡苇11 小时前
Java + Redis + MySQL:工业时序数据缓存与持久化实战(适配高频采集场景)
java·spring boot·redis·后端·spring·缓存·架构
vx-bot55566613 小时前
企业微信ipad协议的消息同步机制与本地缓存策略
缓存·企业微信·ipad
空白诗15 小时前
基础入门 Flutter for Harmony:Text 组件详解
javascript·flutter·harmonyos
喝拿铁写前端15 小时前
接手老 Flutter 项目踩坑指南:从环境到调试的实际经验
前端·flutter
Pluchon16 小时前
硅基计划4.0 算法 并查集&LRU缓存
java·开发语言·数据结构·算法·缓存·哈希算法
renke336416 小时前
Flutter for OpenHarmony:单词迷宫 - 基于路径探索与字母匹配的认知解谜系统
flutter