第1章 缓存策略整体架构设计

构建一个健壮的移动端缓存系统,首先需要从顶层厘清四个核心问题:选用何种持久化方案、如何调度后台任务、是否坚持离线优先、缓存数据如何分层。本章以 Android 平台为例,但原理适用于 iOS/Flutter 等平台。我们将逐一拆解决策树,并给出推荐组合。

1.1 数据持久化选型对比

移动端持久化选型需权衡 读写性能、查询灵活性、存储体积 和 与 WorkManager 的结合成本。下表列出三种主流方案的关键差异。

方案读写性能查询能力存储体积WorkManager 适配难度推荐场景
Room (SQLite ORM)中等(含 ORM 开销)强(SQL + DAO)数据库文件,随数据增长低(直接插入/查询)结构化数据、复杂查询、关联实体
DataStore (Proto/Preferences)高(异步、协程)弱(仅键值对)极小(文件)中(需异步转换)轻量配置、简单缓存元信息
文件存储 (JSON/Protobuf)低(序列化开销)无(全量反序列化)大(文本或二进制)高(需手动管理读写锁)大块数据、离线资源包
推荐组合:业务实体(如文章列表)使用 Room;缓存元数据(如最后更新时间)使用 DataStore;静态资源包(如地图瓦片)使用文件存储+Proto。

1.2 WorkManager 的角色定位

WorkManager 不是缓存容器,而是 缓存刷新引擎。其核心职责包括:

  • 周期性拉取远程数据,检查缓存是否过期
  • 在首次启动或离线恢复后,触发存量缓存的有效性校验
  • 约束条件(网络可用、非低电量)确保后台刷新不会影响用户体验
  • 链式 Work 组合实现 预取 → 解析 → 持久化 流水线
常见误区:不要用 WorkManager 做缓存数据的实时读取。WorkManager 是调度器,不是数据层;读写缓存应通过 Repository 直接调用 Room/DataStore,WorkManager 只负责通知 Repository “该刷新了”。

1.3 离线优先原则

离线优先(Offline First)要求界面渲染 不依赖网络响应。实现步骤:

  1. 加载时优先从 本地缓存 返回数据(即使已过期),保证界面不空白
  2. 后台 WorkManager 同时发起远程请求
  3. 网络成功 → 更新缓存 → 通过 LiveData/Flow 推送新数据到 UI
  4. 网络失败 → 保留过期缓存,并显示“可能不是最新”提示(非阻塞)
核心指标:离线优先实现后,用户首次从点击到看到内容应小于 200ms(缓存命中),而不是等待网络到超时。

1.4 缓存层级划分

将缓存分为三层,每层承担不同职责:

层级存储方式生命周期清理策略示例
L1 – 内存缓存LruCache / MapApp 进程运行期间LRU 驱逐当前会话中频繁读取的配置
L2 – 持久化缓存Room / DataStoreApp 卸载前按时间 TTL 或版本过期用户文章列表、收藏夹
L3 – 资源缓存文件系统可手动清除 / 系统空间不足时DiskLRU 或阈值删除图片缓存、离线地图包

读取时按 L1 → L2 → L3 顺序逐层穿透,写入时同时更新 L1 和 L2(回写模式)。

实践经验:L2 的 TTL 建议设置为 15~30 分钟(新闻类)或更长(配置类)。L3 资源缓存最大体积应限制在 50MB~200MB,通过 WorkManager 定期清理过期文件。

1.5 整体架构 SVG 框架图

缓存策略整体架构 持久化选型 WorkManager 离线优先 Room / DataStore 结构化 + 键值 后台调度 + 约束 周期 / 链式 / 条件 缓存优先 → UI 非阻塞刷新 缓存层级: L1 内存 / L2 持久化 / L3 资源 三级穿透,写入回写 输出: 离线可读 · 秒速加载 · 后台智能刷新 图1-1 缓存策略架构:选型、调度、原则与层级

1.6 本章小结