ArkTS 本地缓存与断网续传:给鸿蒙应用加一个可靠的离线层
ArkTS 本地缓存与断网续传:给鸿蒙应用加一个可靠的离线层
地铁、电梯、弱网会议室,是移动应用最容易“掉链子”的地方:页面白屏、表单丢失、文件下载到一半从头再来。本文用 ArkTS 梳理一套可落地的离线层设计:本地缓存分层、断网续传、离线队列与冲突处理,代码以思路和关键片段为主,可按项目需要调整。
一、先把缓存分层想清楚
不要把所有数据都塞进同一个存储里。建议按“生命周期 + 体积”分三层:
- 配置与轻量状态:用 Preferences 存用户偏好、 token 过期时间、上次同步时间戳等键值数据,读写简单,适合小数据。
- 结构化业务数据:用关系型数据库(RDB)存列表、详情、离线草稿,支持查询、分页和事务,适合需要检索的业务实体。
- 大文件与二进制:图片、文档、安装包等走应用沙箱文件目录,数据库里只存元数据(路径、大小、哈希、分片进度),避免数据库膨胀。
分层的好处是故障隔离:清理图片缓存不会误删业务草稿;数据库升级失败也不会影响偏好设置。
二、缓存策略:先定失效规则,再写代码
缓存最常见的坑不是“存不进去”,而是“不知道什么时候过期”。上线前先回答四个问题:
- 数据多久算过期?新闻列表可能是 5 分钟,用户资料可能是 1 天。
- 过期后是直接丢弃,还是先展示旧数据再后台刷新?后者体验更好,即“ stale-while-revalidate ”。
- 用户主动下拉刷新时,是否强制绕过缓存?
- 磁盘满了怎么办?按最近最少使用(LRU)淘汰,并给缓存目录设上限。
一个实用的读取流程是:先读本地缓存并渲染;同时发起网络请求;请求成功后更新缓存并刷新界面;请求失败且本地有数据时,明确提示“当前为离线数据”。“明确提示”这一点很重要,它把“数据可能滞后”变成用户可理解的状态,而不是悄悄展示旧数据。
三、断网续传:关键在 Range 与进度持久化
大文件下载中断后从头再来,既浪费流量又打击耐心。HTTP 的 Range 请求头就是为此而生的:
- 首次请求时通过 HEAD 或响应头确认服务器是否支持 Range,以及文件总大小。
- 下载时按固定分片(例如 1MB)写入临时文件,每完成一片就把“已完成字节数”持久化到数据库,而不是只保存在内存变量里。
- 中断恢复时读取已完成字节数,带
Range: bytes=<已下载>-继续请求,追加写入同一临时文件。 - 全部完成后校验文件大小,条件允许时再校验哈希,通过后才把临时文件重命名为正式文件。
// 伪代码:恢复下载时的关键逻辑
const downloaded = await db.getProgress(fileId); // 已持久化的字节数
const response = await http.request(url, {
header: { 'Range': `bytes=${downloaded}-` }
});
// 把响应体追加写入临时文件,每写一片更新一次进度
await appendToTempFile(tempPath, response.body, (n) => db.saveProgress(fileId, n));
注意两个细节:其一,服务器不支持 Range 时要诚实降级为完整重下,并告知用户;其二,临时文件与正式文件分离,避免用户打开一个下载了一半的文件。
四、离线队列:把“操作”也存下来
只缓存“读数据”是不够的,离线时用户还会点赞、评论、提交表单。这些写操作需要一个离线队列:
- 把操作序列化为一条记录:操作类型、目标 ID、参数、创建时间、重试次数。
- 联网恢复后按创建时间顺序重放,重放成功后删除记录,失败则按退避策略重试(例如 1 秒、5 秒、30 秒),超过上限后标记为“待人工处理”,而不是无限重试。
- 队列重放期间,界面上对受影响的数据打上“同步中”标记,避免用户重复提交。
离线队列与缓存读取配合起来,就是完整的离线体验:能看旧数据,能做新操作,联网后自动同步。
五、冲突处理:没有银弹,只有取舍
离线编辑最大的麻烦是冲突:用户在离线时改了数据,联网时服务器上的版本也变了。常见策略各有取舍:
- 最后写入获胜:实现最简单,但可能丢数据,适合点赞、阅读进度这类低价值操作。
- 服务端版本获胜并提示用户:适合订单、表单等关键数据,丢本地修改前必须让用户确认。
- 字段级合并:只合并互不冲突的字段,冲突字段留给用户选择,适合富文本、长表单。
- 版本号 + 时间戳:每次写操作带上本地读取时的版本号,服务端发现版本不一致即拒绝并返回最新数据,由客户端决定如何处理。
选策略时先问一句:这条数据丢了,用户会不会投诉?会,就不要用“最后写入获胜”一笔带过。
六、测试清单:别只在 Wi-Fi 下测
离线功能上线前,建议按这张清单走一遍:
- 飞行模式打开应用,核心页面是否可用,提示是否清晰。
- 下载到 50% 时杀进程、断网、重启,恢复后是否从断点继续。
- 离线提交三条操作,联网后是否按顺序同步且不重复。
- 磁盘空间不足时,缓存清理是否生效,应用是否崩溃。
- 系统时间被用户改动后,基于时间戳的过期逻辑是否仍合理。
结语
离线层不是一个“缓存工具类”就能概括的功能,它是一组配合工作的机制:分层存储管数据放在哪,失效规则管数据能用多久,Range 续传管大文件不断线,离线队列管写操作不丢失,冲突策略管多端改动不互相覆盖。先把这五件事想清楚,再写代码,弱网下的应用才会显得“可靠”,而不是“碰巧能用”。
- 点赞
- 收藏
- 关注作者
评论(0)