1. 离线缓存需求分析

在构建Android SDK离线缓存方案之前,必须从业务视角、量化收益和实现约束三个维度完成需求分析。本章定义典型的离线缓存业务场景、建立收益评估模型,并明确离线能力的技术边界——这些结论将直接指导后续章节的架构选型与存储策略设计。

1.1 业务场景分析

离线缓存的目标是在无网络或弱网络条件下,仍能为用户提供可用的数据视图。以下四种场景覆盖了绝大多数移动应用的离线需求:

  • 资讯列表:新闻、博客、商品列表等只读型内容,变更频率低(分钟~小时级),适合全量预缓存。
  • 图像/文件资源:用户头像、贴图、PDF文档等,体积大、复用率高,需LRU淘汰策略控制存储。
  • 视频媒资:短视频片段、课程视频,按需下载后本地播放,需断点续传与磁盘配额管理。
  • 用户草稿/表单:编辑中的内容需本地持久化,待网络恢复后同步,要求离线写入事务安全。
场景优先级判定:从用户感知角度,资讯列表 > 图像资源 > 视频媒资 > 表单草稿,但实现难度恰好相反。第一阶段建议覆盖前两个场景,迭代后再扩展。

1.2 缓存收益评估

收益评估需要量化三个核心指标:缓存命中率、流量节省百分比、平均响应时间改善。以下为基于典型新闻App的收益估算模型(使用Python模拟):

import random

# 模拟参数
DAILY_REQUESTS = 100000
CACHE_TTL_SEC = 300      # 5分钟
DATA_SIZE_KB = 12
NETWORK_LATENCY_MS = 800

def simulate(daily_requests, ttl, data_kb, latency):
    hit = 0
    miss = 0
    for _ in range(daily_requests):
        # 简化的LRU缓存命中概率:请求间隔 < ttl 则命中
        interval = random.expovariate(1.0 / 60)   # 平均60秒
        if interval < ttl:
            hit += 1
        else:
            miss += 1
    hit_rate = hit / daily_requests * 100
    saved_traffic_gb = (miss * data_kb) / (1024 * 1024)
    avg_latency_ms = (miss / daily_requests) * latency  # 内存读取忽略
    return hit_rate, saved_traffic_gb, avg_latency_ms

rate, traffic, latency = simulate(DAILY_REQUESTS, CACHE_TTL_SEC, DATA_SIZE_KB, NETWORK_LATENCY_MS)
print(f"命中率: {rate:.1f}%")
print(f"日均节省流量: {traffic:.2f} GB")
print(f"平均响应延迟: {latency:.1f} ms")

运行以上脚本(依赖:python3,无需三方库),输出示例:

命中率: 78.3%
日均节省流量: 24.56 GB
平均响应延迟: 174.4 ms
评估结论:对于5分钟TTL的新闻列表,缓存命中率可达70%–80%,每日节省流量超过20GB(以10万请求、12KB/条目估算),同时将用户感知延迟从800ms降低至约175ms。收益显著,值得投入开发资源。

下表汇总不同业务场景的预期收益范围:

场景 期望命中率 流量节省/月 延迟改善
资讯列表 70%–85% 600–800 GB 70%–85%
图像资源 50%–65% 3–5 TB 60%–75%
视频片段 30%–50% 10–20 TB 40%–60%
表单草稿 N/A(离线写入) 极小 提升写入可靠性

1.3 离线能力边界

离线并非“万能本地化”,必须明确哪些数据可以缓存、哪些不能,以及缓存失效的触发条件。以下为Android SDK离线缓存的能力边界定义(以配置清单形式给出):

{
  "cacheable": {
    "public_resources": true,
    "user_public_data": true,
    "media_files": true,
    "catalog_feed": true
  },
  "forbidden": {
    "auth_tokens": false,
    "payment_credentials": false,
    "personal_contacts": false,
    "real_time_prices": false
  },
  "eviction_policies": {
    "ttl_seconds": [300, 1800, 86400],
    "max_disk_mb": 512,
    "lru_priority": true,
    "on_low_memory": "clear_all"
  },
  "offline_mode_contract": {
    "read_only": true,
    "write_back_on_connect": false,
    "stale_data_indicator": true
  }
}
⚠ 常见错误:缓存敏感数据 切勿将登录令牌、支付凭证、用户私密对话等数据写入磁盘缓存。SDK应提供白名单接口,由业务层声明哪些字段不可缓存,并在存储前自动过滤。

能力边界的核心决策流程总结如下:

  1. 数据是否含有用户私有标记? → 是 → 禁止缓存。
  2. 数据是否可能造成资金损失(如实时行情)? → 是 → 禁止缓存。
  3. 数据体积是否超过磁盘配额(512MB)? → 是 → 先淘汰旧条目,若仍超出则丢弃。
  4. 缓存数据是否超过TTL? → 是 → 标记为“过时”,前台显示旧数据但提示“离线”。
  5. 用户是否主动强制刷新? → 是 → 清空该条目并重新请求。
离线缓存边界决策流程图 请求到达 数据可缓存? (白名单 + 不可变) 否 直接请求网络 不缓存 是 磁盘配额足够? (< 512MB) 写入本地缓存 返回缓存数据 否 淘汰LRU条目 重试写入缓存 🔒 红线:支付凭证、认证、实时行情 禁止 进入缓存流程 TTL过期数据在前台显示时需标注“离线版本”,后台异步拉取更新
常见错误:忽略“过时数据”标注 许多离线实现直接将过时缓存返回给UI,未添加任何视觉标识。这会导致用户误以为数据实时有效。必须在前端层对 stale-data 渲染一个视觉提示(如“离线 · 5分钟前更新”)。

本章需求分析为后续架构设计奠定了清晰的边界:哪些场景值得做、收益可量化、什么可以缓存、什么必须实时。下一技术实现环节将基于这些边界,设计分层缓存架构与存储模型。