Skip to content

refactor(home): 收敛当前记录链路到 MainViewModel 并修正首页刷新时序#28

Merged
ItosEO merged 7 commits intomainfrom
RefactorLiveRecord
Mar 24, 2026
Merged

refactor(home): 收敛当前记录链路到 MainViewModel 并修正首页刷新时序#28
ItosEO merged 7 commits intomainfrom
RefactorLiveRecord

Conversation

@ItosEO
Copy link
Copy Markdown
Member

@ItosEO ItosEO commented Mar 23, 2026

No description provided.

Copilot AI review requested due to automatic review settings March 23, 2026 17:40
- **日志优化**:
    - 将 `DischargeRecordScanner` 中文件扫描成功的日志以及 `HistoryRepository` 中加载历史记录统计的日志级别由 `DEBUG` 调整为 `VERBOSE`,以减少调试模式下的日志干扰。
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 将“首页当前记录(实时采样 + 当前分段加载/等待态)”链路收敛到 MainViewModel,并调整 server→app 的回调时序:当记录分段切换时,先通知新 RecordsFile,再下发已写入当前分段的实时样本,以修正首页刷新/切段时的展示一致性。

Changes:

  • server 写入链路改为返回 WriteResult(accepted, changedRecordsFile),并在回调线程按“文件切换→样本”顺序通知 app
  • app 侧移除 LiveRecordViewModel,新增 CurrentRecordUiState,首页当前记录卡片直接消费 MainViewModel.currentRecordUiState
  • HistoryRepository 新增按指定 RecordsFile 加载当前记录的结果类型(成功/缺失/样本不足/失败),支持“等待新分段有效样本”状态

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
server/src/main/java/yangfentuozi/batteryrecorder/server/writer/PowerRecordWriter.kt 写入接口返回 WriteResult,在分段创建/状态切换后产出 changedRecordsFile
server/src/main/java/yangfentuozi/batteryrecorder/server/recorder/Monitor.kt 采样回调中按 changedRecordsFileonRecord 顺序通知监听者,并过滤未接受样本
server/src/main/aidl/yangfentuozi/batteryrecorder/server/recorder/IRecordListener.aidl onChangedCurrRecordsFile 改为携带 RecordsFile 参数
app/src/main/java/yangfentuozi/batteryrecorder/ui/viewmodel/MainViewModel.kt 聚合首页当前记录状态与刷新模式,新增等待态/实时点缓冲与分段跟踪逻辑
app/src/main/java/yangfentuozi/batteryrecorder/ui/viewmodel/LiveRecordViewModel.kt 删除(实时点与状态并入 MainViewModel
app/src/main/java/yangfentuozi/batteryrecorder/ui/screens/home/HomeScreen.kt listener 回调对接到 MainViewModel,并调整统计刷新触发时序
app/src/main/java/yangfentuozi/batteryrecorder/ui/model/CurrentRecordUiState.kt 新增:首页当前记录卡片展示状态与实时采样数据结构
app/src/main/java/yangfentuozi/batteryrecorder/ui/components/home/CurrentRecordCard.kt 改为消费 CurrentRecordUiState,支持“分段切换等待态”展示
app/src/main/java/yangfentuozi/batteryrecorder/data/history/HistoryRepository.kt 新增 loadCurrentRecord(recordsFile) 与结果类型,区分样本不足/文件缺失/失败
app/src/main/java/yangfentuozi/batteryrecorder/ui/dialog/settings/CalibrationDialog.kt 适配 AIDL 方法签名变化(忽略 recordsFile 参数)
CLAUDE.md 更新文档:首页当前记录链路收敛到 MainViewModel
AGENTS.md 更新文档:首页当前记录链路收敛到 MainViewModel

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +526 to +530
pendingCurrentRecordsFile = nextPendingRecordsFile
activeLiveRecordsFileName =
nextPendingRecordsFile?.name ?: resolvedCurrentRecord?.name ?: activeLiveRecordsFileName

val nextDisplayStatus = when {
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When统计刷新过程中 targetRecordsFile/activeLiveRecordsFileName 发生变化(例如从旧分段切到 serviceCurrentRecordsFile 或 resolvedCurrentRecord),这里会继续复用 liveBuffer 并直接写入 currentRecordUiState.livePoints,可能导致新分段/新语义下仍展示上一分段的实时曲线点。建议在检测到 activeLiveRecordsFileName 变更时清空 liveBuffer(或按文件名分桶缓存),并同步更新 currentRecordUiState.livePoints 为空,避免跨分段污染。

Copilot uses AI. Check for mistakes.
Comment on lines +143 to 146
viewModel.refreshStatisticsTrackingCurrentRecord(
context = context,
request = statisticsRequest
)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个 LaunchedEffect 在 delay(1500) 前检查了 lifecycle 状态,但 delay 结束后没有再次确认仍处于 STARTED/RESUMED,就会在用户已离开首页或进入后台时触发 refreshStatisticsTrackingCurrentRecord,造成不必要的 Sync/IO 与状态更新。建议在 delay 后再次检查 lifecycle(或用 repeatOnLifecycle/withFrameNanos 等更生命周期安全的方式)再执行刷新。

Suggested change
viewModel.refreshStatisticsTrackingCurrentRecord(
context = context,
request = statisticsRequest
)
if (lifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
viewModel.refreshStatisticsTrackingCurrentRecord(
context = context,
request = statisticsRequest
)
}

Copilot uses AI. Check for mistakes.
Comment on lines +96 to +99
private fun Throwable.isInsufficientSamplesError(): Boolean {
return this is IllegalStateException &&
message?.startsWith(NOT_ENOUGH_VALID_SAMPLES_PREFIX) == true
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isInsufficientSamplesError 通过匹配 IllegalStateException 的 message 前缀来判断“样本不足”,这对 RecordsStats 的错误文案有强耦合,后续一旦调整异常信息就会导致等待态判断失效。建议改为抛出/传递一个明确的异常类型(或在 shared 层提供可复用的常量/错误码)来做分支判断。

Copilot uses AI. Check for mistakes.
ItosEO added 5 commits March 24, 2026 02:21
- **采样流程重构**:
    - 抽取 `waitUntilSamplingAllowedLocked` 方法,统一管理采样前的状态判定逻辑。
    - 将采样主循环简化为“等待授权 -> 执行采样 -> 间隔等待”的线性流程,提高代码可读性。
- **性能优化**:
    - 在轮询模式下,仅在进入判定循环时刷新亮屏状态,避免每次写入文件前执行额外的系统调用(`iPowerManager.isInteractive`),降低开销。
- **状态管理**:
    - 优化了暂停与恢复采样的日志记录与状态切换逻辑。
    - 明确区分了基于回调的亮屏状态监听与基于轮询的刷新机制,确保采样行为符合 `screenOffRecord` 配置。
- **数据模型**:
    - 在 `CurrentRecordUiState` 中新增 `recordsFileName` 字段,用于标识当前 UI 状态所属的记录文件。
    - 引入私有数据结构 `LiveSegmentBuffer` 统一管理实时采样点及其对应的文件名,替代原有的分散变量。
- **状态同步与切换**:
    - 新增 `switchActiveLiveSegment` 方法,在记录文件切换时强制清空采样缓存,确保采样曲线与分段语义严格对应,避免旧数据的残影。
    - 重构 `onLiveSampleReceived` 逻辑,增加对 `pendingCurrentRecordsFile` 的校验,确保在实时采样到来时 UI 状态能正确关联到目标文件。
    - 优化 `onLiveStatusChanged` 中的状态推导逻辑,根据最新的 `resolvedCurrentRecord` 或 Service 状态同步更新活动分段,并使用快照更新 UI。
- **稳定性与清理**:
    - 统一 `clearDisplayedHomeState` 的清理逻辑,确保重置时同步清除 `liveSegmentBuffer` 中的状态。
- **逻辑重构**:移除 `buildChangedRecordsFile` 私有方法,将其逻辑内联至 `write` 方法的主流程中,直接处理 `segmentFile` 的状态转换。
- **日志增强**:优化了文件切换时的日志输出,明确区分“新分段已就绪”与“状态切换后续写当前分段”两种触发原因,并确保日志中的文件信息与返回的 `WriteResult` 保持一致。
- **逻辑重构**:
    - 移除 `waitUntilSamplingAllowedLocked` 方法,将采样等待逻辑直接整合进 `MonitorThread` 的主循环中,简化执行流程。
    - 调整采样与等待的顺序,确保在亮屏或开启熄屏记录时先执行一次采样再进入间隔等待。
- **亮屏状态监测**:
    - 优化了 `alwaysPollingScreenStatusEnabled` 模式下的状态更新逻辑。在暂停采样期间,通过循环轮询 `iPowerManager.isInteractive` 状态,确保能及时响应屏幕状态变化并恢复采样。
    - 统一了状态变化的日志输出,便于追踪亮屏状态切换。
- **状态管理**:
    - 细化了 `paused` 状态的切换时机,确保 UI 或日志能准确反映当前的采样挂起状态。
- **数据层**:
    - **PowerRecordWriter**:将 `WriteResult` 从 `data class` 重构为 `sealed interface`,明确划分为 `Accepted`(已写入)、`Rejected`(已丢弃)和 `Changed`(文件已切换)三种状态。
    - 优化了 `BaseDelayedRecordWriter` 的写入逻辑。在文件切换时强制返回 `Changed` 状态,并收紧了状态转换的语义,消除原先布尔组合产生的歧义。
    - 增加对 `segmentFile` 异常为空时的错误日志埋点,以便观察采样线程的状态同步问题。
- **核心逻辑**:
    - **Monitor**:适配新的 `WriteResult` 密封类。在采样循环中根据不同状态精确触发回调,确保只有在 `Accepted` 或 `Changed` 时才分发 `onRecord`,并在 `Changed` 时同步更新记录文件。
@ItosEO ItosEO merged commit 7762f24 into main Mar 24, 2026
1 check passed
@ItosEO ItosEO deleted the RefactorLiveRecord branch March 24, 2026 23:39
ItosEO added a commit that referenced this pull request Mar 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants