Android 离线同步:补偿队列与脏数据回收怎么收口

作者: Android学习网 分类: Android网络编程 发布时间: 2026-04-08 10:39

## Android 离线同步问题

Android 离线同步最难的不是把请求发出去,而是断网、重试、恢复网络之后,怎么确认本地状态、远端结果和补偿队列三边没有错位。只要其中一边慢一步,用户看到的就不是‘同步稍后完成’,而是旧数据回写、重复提交或者列表状态来回跳。这个问题更像数据账本收口,不是平台升级或 ROM 适配那一路。

## 方案

最稳的做法是单独建一张 pending queue,把本地写入、待同步状态、最后尝试时间和失败原因全部挂进去。然后把状态拆成 queued、acked、applied 三段,只有真正走到 applied,Android 离线同步才算闭环。这样一来,问题不会永远堆成一句“同步偶发失败”,而是能明确落到队列、回写确认或脏数据回收其中一段。

## 示例代码

1. 待同步队列表

@Entity(tableName = "pending_sync")
data class PendingSyncEntity(
    @PrimaryKey val id: String,
    val payload: String,
    val state: String,
    val updatedAt: Long
)

2. Worker 执行入口

class SyncWorker(
    appContext: Context,
    params: WorkerParameters
) : CoroutineWorker(appContext, params) {
    override suspend fun doWork(): Result {
        return Result.retry()
    }
}

3. 队列观测命令

adb shell dumpsys jobscheduler | findstr SyncWorker
adb shell am broadcast -a androidx.work.diagnostics.REQUEST_DIAGNOSTICS -p com.example.app

## 注意点

Android 离线同步最危险的不是一次失败,而是同一份 pending 队列同时装着“可自动重试”“需要人工合并”“已经过期可丢弃”三类数据。只要这三类不分桶,后面每次回查都会越查越乱。真正该做的是先把脏数据按风险分桶,再决定自动修还是人工介入。

## 报错与排查

1. 队列一直不出队

fun shouldRetrySync(retryCount: Int, hasNetwork: Boolean): Boolean {
    return hasNetwork && retryCount < 5
}

2. 服务端已成功但本地未确认

data class SyncAck(
    val localId: String,
    val remoteVersion: Long,
    val applied: Boolean
)

## 可运行片段

1. 最小状态机

enum class SyncState {
    QUEUED, ACKED, APPLIED, FAILED
}

2. 最小演示入口

fun runOfflineSyncDemo() {
    val state = SyncState.QUEUED
    println(state)
}

3. 回归命令

adb shell dumpsys jobscheduler | findstr SyncWorker
adb logcat -d | findstr /I "retry pending conflict ack"
sqlite3 app.db "select id,state,updatedAt from pending_sync order by updatedAt desc limit 20;"

补一句最关键的回归要求:不要只确认 Worker 重新跑了,还要确认 pending 队列确实减少、ack 状态被写回、本地列表已经切到最新版本。否则 Android 离线同步 看起来恢复了,实际上只是把旧问题延后。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注