Files

45 lines
3.4 KiB
Markdown

# 行情表格请求切换的订阅与缓冲清理
## 修复提交
| 仓库 | 分支 | Commit ID | 说明 |
| --- | --- | --- | --- |
| `harmony-ths-futures-apm-oom` | `work-20260820-clz-FUHM-1979-apm-oom` | `5f6e007c7f431521350a68543c4db5314a8c644f` | 修复 `TableRequestClient` 订阅泄漏 |
| `harmony-ths-futures-apm-oom` | `work-20260820-clz-FUHM-1979-apm-oom` | `2ca4759c4e0212b4c80c41b94a0ae1339569e89c` | 完善请求切换时的统一清理逻辑 |
## 问题
行情列表通过 `TableRequestClient` 发起请求,并在带 `newrealtime=1` 的请求中向 `RealDataManager` 注册实时订阅。请求队列映射、实时订阅和请求缓冲分别以 instanceId、instanceId、`frameId + pageId + instanceId` 关联。
原有 `setPageId()` 先覆盖成员 `pageId`,再移除请求队列映射;随后无法获得旧 instanceId,也没有同步清理旧实时订阅与旧请求缓冲。切换行情分组时,`RealDataManager` 可能持续持有旧表格订阅并合并推送数据,造成 Local Heap 持续增长,最终有 OOM 风险。
## 优化方案
1. `setPageId()` 在覆盖成员前保存旧 `pageId`,递增请求生命周期版本并取消待执行通知,再统一解绑旧请求。
2. 新增私有 `detachCurrentRequest(oldPageId)`:调用 `RequestQueueManagement.removeByClient(this)` 原子取得并移除旧 instanceId 映射;当旧 ID 有效时,用该 ID 移除 `RealDataManager` 订阅,并以旧 `pageId` 删除对应请求缓冲。
3. `removeSubscriber()``release()` 复用同一解绑逻辑,避免多个生命周期出口清理策略不一致。
4. 保留既有异步版本校验和 `setTimeout` 取消逻辑,防止过期解析结果或通知闭包继续持有表格数据。
## 影响范围
- 仅修改 `lib_baseUI``TableRequestClient` 请求切换和释放生命周期。
- 不修改协议报文、请求参数、表格解析、实时数据合并或 UI 展示逻辑。
- 请求未建立队列映射时,清理操作保持幂等并直接返回。
## 预期收益与边界
每次行情分组切换和页面销毁都会同时释放旧请求的队列映射、实时订阅及请求缓冲,避免孤儿订阅继续持有全量表格并接收实时推送,从而抑制 Local Heap 随切页线性增长。
该修改只治理 `TableRequestClient` 链路的引用滞留;图形内存、Web、Native/CPP 堆及其他业务模块的内存增长仍需按各自链路继续分析。`removeSubscriber` 与缓冲删除均按旧 instanceId 执行,因此不会误删新请求。
## 验证建议
1. 执行 `devecocli build --modules entry@default`,确认 ArkTS 编译和打包通过。
2. 安装新 HAP 后,在“行情 → 国内”页的“全部主力 / 能源”等分组间连续切换 20~50 次,再离开列表页。
3. 使用临时调试计数验证每次切换后旧订阅和旧请求缓冲各减少一项,待执行通知数归零;验证完成后不保留计数日志或缓冲快照统计代码。
4. 检查应用崩溃日志,并结合 APM/HiLog 观察 Local Heap 在循环切换期间不再线性增长。
## 本次验证结果
在模拟器上完成 20 次同一活跃 `TableRequestClient` 的分组切换:每轮旧订阅数由 2 降至 1、请求缓冲数由 4 降至 3,待执行通知数始终为 0;离开行情列表后订阅数由 1 降至 0。未发现该应用的崩溃日志。上述计数日志仅用于本次验收,已从正式代码移除。