1. Compose埋点架构全景:状态层、事件层、上报层

在 Jetpack Compose 的声明式 UI 体系下,埋点数据不再由用户点击事件被动触发,而是由状态驱动自动流转。传统的 Activity/Fragment 埋点方案在 Compose 中面临 状态感知缺失、组合生命周期不可控、上报时机混乱 三大核心问题。本章从架构全景出发,定义 状态层 → 事件层 → 上报层 的三层边界,给出每一层的组件职责与数据流契约。

1.1 三层架构总览

整个埋点流转体系划分为三个彼此独立、通过接口通信的层级。状态层感知 Compose 状态变化并生成原始事件;事件层对原始事件进行校验、增强、缓冲和策略过滤;上报层负责将合规事件序列化、批量压缩并发送到远端服务。三层之间不允许跨层调用,也不允许反向依赖。

层级边界核心职责对外依赖
状态层Compose 运行时 + ViewModel监听 Snapshot 快照变化,采集状态快照并包装为原始事件Compose State / SnapshotFlow
事件层ViewModel / UseCase / Repository事件去重、合并、采样、增强业务上下文Coroutine Flow / Channel
上报层网络模块 / 本地持久化批量打包、重试、配额控制、远端写⼊OkHttp / Retrofit / Room
设计原则: 每一层的修改不应影响其他层的逻辑。状态层只关心“发生了什么状态变化”,事件层只关心“如何加工事件”,上报层只关心“如何可靠送达”。
Compose 埋点三层架构全景 状态层 · State Layer StateHolder Compose State 容器 SnapshotFlow 快照观察协程 ComposeState mutableStateOf 包装 原始事件 Flow 事件层 · Event Layer EventCollector 原始事件收集器 EventProcessor 去重·采样·增强 EventBuffer 内存缓冲队列 合规事件 Flow 上报层 · Report Layer ReportDispatcher 上报调度器 BatchUploader 批量压缩上传 RetryManager 指数退避重试 信任链路:状态层提供可追溯的 Snapshot 版本号 → 事件层携带业务签名 → 上报层校验完整性后持久化。

1.2 边界与组件职责

三层之间的边界由 不可变事件契约 定义。状态层输出的 RawEvent 只包含状态快照和版本戳;事件层输出的 TrackEvent 携带业务维度、采样标记和路由标签;上报层最终消费 ReportPacket 进行序列化与传输。

  • 状态层 — 唯一允许直接依赖 Compose State / SnapshotFlow 的层级。负责将 mutableStateOf 的变化映射为事件流,不对事件做任何业务判断。
  • 事件层 — 纯 Kotlin 协程模块,不依赖任何 Android 或 Compose 运行时。负责事件的 去重(Dedup)、采样(Sampling)、上下文增强(Enrich) 和 缓冲(Buffer)。
  • 上报层 — 依赖网络框架和本地数据库。负责将事件打包为 JSON/Protobuf,通过 批量合并 降低请求次数,并通过 指数退避重试 保证最终可达。
边界检查清单: 状态层代码中禁止出现“上报”或“网络”字样;事件层代码中禁止出现 Compose 或 View 导入;上报层代码中禁止出现 mutableStateOf 或 snapshotFlow 调用。

1.3 数据流与控制流

数据流是单向的:状态 → 事件 → 上报。控制流则通过 策略注入 反向作用于事件层和上报层,例如采样率更新、上报频率调节、事件黑名单等。

// 状态层:通过 SnapshotFlow 感知 Compose 状态变化
@Composable
fun TrackableScreen(viewModel: TrackableViewModel) {
    val uiState by viewModel.uiState.collectAsState()

    // 状态层自动采集
    LaunchedEffect(uiState) {
        viewModel.stateLayer.emitRawEvent(
            RawEvent(
                snapshot = uiState.toSnapshot(),
                version = snapshotFlow { uiState }.first()
            )
        )
    }
}

// 事件层:处理并转发
fun EventProcessor.process(raw: RawEvent): TrackEvent? {
    return when {
        raw.isDuplicate() -> null          // 去重
        !sampler.shouldSample(raw) -> null  // 采样
        else -> raw.enrich(metadataProvider())  // 增强
    }
}

// 上报层:批量调度
suspend fun ReportDispatcher.dispatch(event: TrackEvent) {
    buffer.put(event)
    if (buffer.size >= batchSize) {
        uploader.upload(buffer.flush())
    }
}

1.4 信任链路与版本追踪

数据在层间流转时,必须携带 不可篡改的签名链。每一层在收到前层数据后,会追加自己的校验值再传递给下一层。状态层为每个 RawEvent 生成 snapshotVersion;事件层附加 eventSignature(业务 ID + 时间戳 HMAC);上报层写入 reportChecksum 后持久化。

风险点: 如果状态层在 Composable 重组期间多次发射相同快照,事件层必须实现幂等去重,否则会导致同一状态被上报多次。推荐在 EventProcessor 中维护一个 LRU 缓存,以 snapshotVersion 为键做去重。

1.5 选型权衡

决策点方案 A方案 B推荐场景
状态采集方式SnapshotFlow + StateCompose 效应 + 手动发射统一用 SnapshotFlow,避免效应泄漏
事件缓冲位置内存 Channel (Buffer)Room 持久化缓冲低频事件用内存,高频/重要事件用 Room
上报触发策略定时批量 (10s 窗口)阈值触发 (满 N 条立即上报)对实时性要求不高时用定时批量,降低请求量
重试机制指数退避 + 最大 3 次线性重试 + 持久化队列网络不稳定场景用指数退避;离线场景用持久化队列

1.6 落地步骤与验收标准

将三层架构落地到现有 Compose 项目中,建议按以下顺序推进:

  1. 裁剪状态层 — 在目标 Composable 中注入 StateLayer,定义要追踪的 State 变量列表,验证每次状态变化都能产出 RawEvent。
  2. 搭建事件层流水线 — 实现 EventCollector + EventProcessor + EventBuffer,用单元测试验证去重和采样逻辑。
  3. 对接上报层 — 接入网络 SDK,配置批量上传参数和重试策略,编写集成测试验证端到端上报。
  4. 注入控制流 — 通过 ViewModel 或配置中心下发采样率、黑名单等策略,观察事件层是否按预期过滤。
  5. 全链路压测 — 在 200+ 状态变化/秒的极限场景下,验证事件层不 OOM、上报层不丢数据。
验收标准(每个标准必须可量化测试):
✅ 状态层每秒 500 次快照发射时,事件层丢事件率 < 0.01%。
✅ 上报层在弱网环境(丢包率 30%)下,24 小时内事件最终送达率 > 99.9%。
✅ 三层代码之间无循环依赖,编译期可通过 module-info 或 gradle 依赖检查验证。
✅ 单次链路延迟(状态变化 → 上报写入)不超过 500ms(Wi-Fi 环境)。