取餐记录定时补传实现计划
执行方式: 在
loop_upload_pick分支按测试驱动方式逐项实现;所有步骤完成后执行 JDK 8 单元测试、Java 编译和 APK 构建验证。
目标: 仅修改 Android 端,为取餐记录增加固定 3 分钟、每轮最多 20 条、严格串行且全状态留痕的自动补传能力。
架构: 使用 AlarmManager 固定触发一次性唯一 WorkManager;纯 Java 处理器决定批次上限、串行顺序和断网停止;协调器统一实时上传与周期上传;SQLite 主表保存当前状态,追加日志表保存完整迁移轨迹。
技术栈: Java 8、SQLiteOpenHelper、WorkManager 2.5、AlarmManager、Retrofit、JUnit 4。
任务 1:建立可测试的补传策略
文件:
- 新建
app/src/test/java/com/zhct/traybinding/upload/PickMealUploadPolicyTest.java - 新建
app/src/test/java/com/zhct/traybinding/upload/PickMealRetryProcessorTest.java - 新建
app/src/main/java/com/zhct/traybinding/upload/PickMealUploadPolicy.java - 新建
app/src/main/java/com/zhct/traybinding/upload/PickMealUploadResult.java - 新建
app/src/main/java/com/zhct/traybinding/upload/PickMealRetryProcessor.java
步骤:
- 先编写失败测试,覆盖 20 条上限、ID 顺序、同步逐条处理、单条失败继续、中途断网停止、无网络不处理、5g 阈值、服务端成功/拒绝/失败分类和失败 10 次封顶。
- 运行
:app:testDebugUnitTest,确认测试因生产类不存在而失败。 - 实现最小纯 Java 策略和处理器。
- 再次运行单元测试,确认全部通过。
任务 2:升级数据库和状态日志
文件:
- 修改
app/src/main/java/com/zhct/traybinding/database/CustomDBHelper.java - 修改
app/src/main/java/com/zhct/traybinding/bean/PickMealRecord.java - 修改
app/src/main/java/com/zhct/traybinding/database/PickMealRecordImpl.java
步骤:
- 数据库版本从 2 升至 3。
- 主表增加
retry_count、last_attempt_time、last_error_code、last_error_message、upload_updated_at。 - 新建
pick_record_upload_log追加日志表和查询索引。 - 增加最早优先且最多 20 条的查询、
PENDING/FAILED -> UPLOADING原子占用、结果落库、IGNORED/REJECTED/FAILED_FINAL终态和 10 分钟占用恢复。 - 编译验证所有字段映射和接口签名。
任务 3:统一实时上传与周期补传
文件:
- 新建
app/src/main/java/com/zhct/traybinding/upload/PickMealUploadCoordinator.java - 修改
app/src/main/java/com/zhct/traybinding/main/WeightMainActivity.java
步骤:
- 协调器复用现有
uploadPickMealInfo同步请求,不修改接口字段。 - 实时上传继续最多尝试 3 次,但每次失败都计入总失败次数 10 次上限。
- 周期补传每条只请求一次,失败后继续下一条。
- 小于 5g 或关键数据无效的记录标记为
IGNORED。 code=0标记UPLOADED,code=1标记REJECTED,其余错误标记FAILED/FAILED_FINAL。- Activity 保留原成功、拒绝和失败提示/日志入口。
任务 4:接入 3 分钟唯一后台任务
文件:
- 新建
app/src/main/java/com/zhct/traybinding/utils/PickMealRetryScheduler.java - 新建
app/src/main/java/com/zhct/traybinding/workmanager/PickMealRetryWorker.java - 修改
app/src/main/java/com/zhct/traybinding/receiver/AlarmReceiver.java - 修改
app/src/main/java/com/zhct/traybinding/application/CptApplication.java
步骤:
- App 初始化后安排第一次 3 分钟闹钟。
- 闹钟触发后立即续订下一次,并在有网络时提交唯一 Worker。
- Worker 开始时再次检查网络、恢复超时占用、执行最多 20 条的串行批次。
- 使用
ExistingWorkPolicy.KEEP和数据库原子占用避免任务重叠。 - 无网络时不选取记录、不修改状态和重试次数。
任务 5:验证和交付记录
文件:
- 新建
work_android/ZhctTrayAndWeight/change_records/2026-07-13-pick-meal-periodic-retry.md - 新建同名 HTML 文件。
验证命令:
JAVA_HOME=$(/usr/libexec/java_home -v 1.8) bash ./gradlew :app:testDebugUnitTest --no-daemon
JAVA_HOME=$(/usr/libexec/java_home -v 1.8) bash ./gradlew :app:compileDebugJavaWithJavac --no-daemon
JAVA_HOME=$(/usr/libexec/java_home -v 1.8) bash ./gradlew :app:assembleDebug --no-daemon
git diff --check
完成标准:
- 单元测试证明批次、串行、断网和状态策略。
- Java 编译和 APK 构建成功。
- Android 代码未修改接口地址和请求字段。
- 变更记录同时存在 Markdown 与 HTML 两个版本。