羽毛球学习 HarmonyOS 设计续篇(24):图片缓存与列表滚动稳定性方案

发布时间:2026/9/27 9:21:35

羽毛球学习 HarmonyOS 设计续篇(24):图片缓存与列表滚动稳定性方案
一、现有边界能显示图片不等于有缓存治理课程、资讯和装备卡片已经能够在网络地址与本地资源之间选择加载失败时也有兜底图。这解决的是“有没有图”还没有回答快速滚动时是否重复下载、解码任务能否取消、内存压力如何控制、同一地址的不同尺寸是否会相互污染。当前设置页中的“清理缓存”主要处理浏览历史也不能作为图片缓存已经落地的证据。因此本文定位为待实施方案。目标不是承诺列表已经达到某个帧率而是建立一套可验收的图片管线列表只请求当前卡片需要的尺寸相同请求只执行一次离屏任务可以取消内存超限时按确定规则淘汰磁盘不可用时仍可退回本地占位图。当前已有仍需设计不纳入本期网络封面地址、本地兜底资源、卡片列表缓存键、预算、并发合并、取消、指标图片编辑、云端 CDN 改造、预下载整套课程页面级刷新和空状态离屏回收与失败可见性预测用户下一次访问二、先定义两级预算再讨论命中率图片缓存不能以“尽量多存”为策略。内存层适合保存已经解码、可直接绘制的小图磁盘层保存压缩后的原始响应两者需要独立预算。建议内存预算取设备可用内存的较小比例并设置硬上限磁盘预算按应用数据规模设定例如 80 MB。收到内存压力通知时内存层应立即缩减到目标水位而不是等待下次启动。export interface ImageBudget { memoryBytes: number diskBytes: number maxParallelRequests: number prefetchDistance: number } export const DEFAULT_IMAGE_BUDGET: ImageBudget { memoryBytes: 24 * 1024 * 1024, diskBytes: 80 * 1024 * 1024, maxParallelRequests: 4, prefetchDistance: 2 } export interface CacheUsage { memoryBytes: number diskBytes: number inFlightCount: number evictionCount: number }预算是稳定性的前提。没有预算时命中率越高可能意味着驻留对象越多最终以卡顿或系统回收结束有了预算命中率、淘汰次数和失败率才有共同解释。三、缓存键必须包含尺寸、裁剪方式和资源版本只用 URL 作为键会产生隐蔽错误列表缩略图可能污染详情页大图圆角裁剪版本也可能复用未经裁剪的结果。建议将标准化地址、目标宽高、缩放方式、主题和版本摘要一起计算为键。服务端若提供 ETag 或 Last-Modified可进入版本摘要没有版本信息时使用带有效期的地址摘要。export interface ImageVariant { widthPx: number heightPx: number fit: cover | contain theme: light | dark revision: string } export function imageCacheKey(url: string, variant: ImageVariant): string { const normalized url.trim().toLowerCase() return [ normalized, variant.widthPx, variant.heightPx, variant.fit, variant.theme, variant.revision ].join(|) }键维度缺失后的风险建议来源宽高与缩放方式小图被放大、重复解码卡片布局规格主题深浅色资源串用当前主题状态版本摘要旧封面长期驻留ETag、更新时间或业务版本四、请求合并、取消与提交必须在协调器中完成列表滚动会让多个卡片在短时间内请求同一图片。协调器先查内存再查磁盘最后才进入网络相同键已有进行中任务时新的订阅者共享 Promise。卡片离屏只取消自己的订阅最后一个订阅者离开才中止底层任务避免一个组件误伤另一个仍可见组件。export type ImageSource memory | disk | network | fallback export interface ImageResult { source: ImageSource pixelMap?: PixelMap errorCode?: string } export interface ImageTicket { key: string result: PromiseImageResult cancel(): void } export interface ImageCoordinator { request(url: string, variant: ImageVariant): ImageTicket trimMemory(level: moderate | critical): void clearDisk(): Promisevoid usage(): CacheUsage }磁盘写入需要先写临时文件、校验长度或摘要再原子替换正式文件。应用被杀或空间不足时临时文件可以在下次启动清理不能把半截文件登记为缓存命中。五、列表单元只消费视觉状态不直接管理网络卡片需要的状态只有占位、加载成功、加载失败和已取消。网络重试、磁盘路径、淘汰顺序不应进入 UI。列表项出现时创建 ticket消失时取消键改变时先取消旧任务再绑定新任务。结果回调还要比较当前键防止旧请求覆盖复用后的卡片。export type CoverVisual | { kind: placeholder } | { kind: ready; pixelMap: PixelMap; source: ImageSource } | { kind: failed; retryable: boolean } export class CoverPresenter { private generation: number 0 async bind(ticket: ImageTicket): PromiseCoverVisual { const current this.generation const result await ticket.result if (current ! this.generation) { return { kind: placeholder } } if (result.pixelMap) { return { kind: ready, pixelMap: result.pixelMap, source: result.source } } return { kind: failed, retryable: result.errorCode ! INVALID_URL } } invalidate(): void { this.generation 1 } }六、失败与降级要对用户无惊扰、对诊断有信号断网时优先显示磁盘副本磁盘无副本则使用本地兜底图。解码失败应删除损坏条目并最多重试一次避免循环。空间不足时暂停磁盘写入但保留受预算约束的内存层。地址非法直接进入不可重试状态。滚动期间不弹连续 Toast错误通过卡片占位和聚合指标表达。失败页面表现后台动作恢复条件断网磁盘副本或兜底图标记网络未命中网络恢复后按需重试文件损坏兜底图删除条目、单次重新下载校验通过空间不足已显示图片保持停止磁盘写入清理后重新开放内存压力可见项保持优先淘汰离屏和低频项水位下降七、取舍稳定优先于激进预取预取距离越大首屏之后的体验可能更顺但会与当前可见请求争夺带宽和解码时间。第一阶段只预取可见窗口之后两项快速滑动时取消低优先级预取。磁盘层采用 LRU 加有效期而内存层采用带成本权重的 LRU尺寸更大的对象成本更高更早进入淘汰候选。建议记录memoryHit、diskHit、networkLoad、decodeFailure、cancelled和visibleReadyLatencyMs。这些指标只用于判断管线是否稳定不在未采集数据前写出命中率或帧率结论。还要避免把缓存命中率当作唯一目标。若为了提高命中率长期保留大尺寸对象解码内存和垃圾回收压力可能反而拉长可见图片的就绪时间。参数校准应同时观察可见延迟、峰值内存、取消比例和网络流量并按低端设备的结果确定默认预算高端设备可以在运行时放宽水位但不能改变键模型和失败合同。八、实施顺序与证据计划第一步落地键模型、内存预算和单元测试第二步增加请求合并与 generation 防串图第三步加入磁盘索引、原子写入和启动清理第四步接入列表生命周期与两项预取第五步再做压力测试和参数校准。验收至少覆盖连续快速滚动 200 个卡片不串图相同键并发只触发一次底层加载卡片离屏后任务可取消损坏文件不会作为命中返回断网有兜底内存压力后用量回落到目标水位清理缓存不删除收藏等用户资产。后续证据应包含性能采样、缓存指标、断网录屏和内存压力日志取得这些证据后才能把文章定位升级为实战。参考HarmonyOS 图片开发指导。九、总结图片缓存不是给Image外面包一层工具类而是一条有预算、有版本、有取消、有原子提交的资源管线。列表稳定性也不能靠“看起来不卡”判断。先把键、任务和降级合同固定再用真实数据校准预算才能让封面加载在快速滚动、弱网和内存压力下保持可解释。

相关新闻

FiPy偏微分方程求解器:Python科学计算的强大有限体积法工具

FiPy偏微分方程求解器:Python科学计算的强大有限体积法工具

2026/9/27 9:21:34

FiPy偏微分方程求解器:Python科学计算的强大有限体积法工具 【免费下载链接】fipy FiPy is a Finite Volume PDE solver written in Python 项目地址: https://gitcode.com/gh_mirrors/fi/fipy 你是否正在寻找一个能够轻松求解复杂偏微分方程的Python工具&am…

隔离栅极驱动器ISO5452:原理、设计与实战应用解析

隔离栅极驱动器ISO5452:原理、设计与实战应用解析

2026/9/8 15:50:46

1. 隔离栅极驱动器:电力电子的“神经与肌肉”接口 在工业电机驱动、光伏逆变器或者大功率UPS的电路板上,你总能找到一类不起眼但至关重要的芯片——隔离栅极驱动器。它就像一位训练有素的“翻译官”和“保镖”,站在微控制器(大脑&…

如何用Mate Engine打造个性化桌面伴侣:5个创新应用场景

如何用Mate Engine打造个性化桌面伴侣:5个创新应用场景

2026/8/27 0:52:14

如何用Mate Engine打造个性化桌面伴侣:5个创新应用场景 【免费下载链接】Mate-Engine A free Desktop Mate alternative with a lightweight interface and custom VRM support, though with more features. 项目地址: https://gitcode.com/gh_mirrors/ma/Mate-En…

CANN/GE ACL数据集缓冲区添加函数

CANN/GE ACL数据集缓冲区添加函数

2026/9/26 19:14:12

aclmdlAddDatasetBuffer 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、Te…

用ffmpeg高效批量调整图片尺寸的实战指南

用ffmpeg高效批量调整图片尺寸的实战指南

2026/9/27 1:30:29

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱

2026/9/27 1:30:37

Transformers 音频特征提取工具库 audio_utils 全解析:从 Mel 刻度换算到对数 Mel 频谱 【免费下载链接】transformers 🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and mu…

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南

2026/9/27 1:30:35

RustFS 多节点集群重启与滚动升级实战:Readiness、Quorum 与 Degraded 模式完全指南 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system sup…

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

Java Integer缓存揭秘:128陷阱原理、避坑与面试全解

2026/9/27 1:30:34

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据

2026/9/26 16:36:51

RustFS Scanner 数据用量发布权威性决策:配额准入如何获得可用的权威依据 【免费下载链接】rustfs 🚀2.3x faster than MinIO for 4KB object payloads. RustFS is an open-source, S3-compatible high-performance object storage system supporting mi…

远程协作的工作台整理

远程协作的工作台整理

2026/9/26 14:29:04

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/26 13:57:22

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/26 23:35:16

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…