Files
FruitServer/docs/plans/2026-10-21-K95-feed-switch-loading.md
T

3.7 KiB
Raw Blame History

K95 修复首页频道快速切换卡 Loading

目标

  • 频道请求完成后始终写回发起请求的频道缓存,不再因用户切走而丢失结果。
  • 每频道明确区分 loaded / loading / in-flight / error,无请求时绝不显示首屏转圈。
  • 首屏和刷新请求增加可注入的 10 秒超时兜底。
  • PlayerLogic 保证连续 feed 更新串行应用,只让最后一次 feed/session 生效。

分支

  • ReelShort:fix/k95-feed-switch-loading,从 origin/develop 创建。
  • FruitServer 仅提交计划与 PROGRESS,不改功能代码。

A. HomeFeedController

每个频道状态增加:

  • List<Drama> dramas
  • String? cursor
  • bool hasMore
  • bool loaded
  • bool loading
  • bool loadingMore
  • String? lastError
  • int requestSeq
  • Future<bool>? inFlight

请求规则:

  1. 响应成功/失败都写入发起请求的频道状态。
  2. 只有频道仍为当前频道时才 notifyListeners。
  3. requestSeq 只比较同一频道的新旧请求,不参与跨频道过滤。
  4. 超时时间通过构造参数注入,默认 10 秒。
  5. loadingFirstPage = !loaded && loading。
  6. selectChannel:
    • 有缓存:同步显示,未在飞时后台静默刷新
    • 无缓存且正在飞:等待现有请求,不重复发
    • 无缓存且有历史错误:自动重试
    • 从未加载:发起首屏请求
  7. refreshCurrent 同样复用 in-flight,防止并发重复刷新。
  8. loadMore 失败保留 cursor/hasMore,允许下次继续重试。

B. PlayerLogic / PlayerPage

B1 Feed revision

  • PlayerLogic 增加 int feedRevision。
  • 每次 updateFeed 自增 revision,记录最新目标 feed。
  • _replaceSession 与 selectEpisode 在 await 后校验 revision,过期流程直接返回。
  • 连续 updateFeed 使用串行队列:当前应用结束后再应用最新待处理 feed。

B2 空队列与频道切换

  • 空 feed 不创建新 session,只清空 queue/visibleIndices 并停播。
  • 空 → 非空必须恢复 route visible,并 select 第 0 个。
  • 频道变化通过额外 reset 标志传入 updateFeed,即使 drama id 列表相同, 也重置到第 1 个并开始播放。

B3 PlayerPage 更新判定

  • didUpdateWidget 用 feedDramas 的 drama id 列表签名判断内容变化。
  • 同一列表的新 List 实例不重复 updateFeed。
  • 频道变化始终触发 updateFeed,并传 resetToFirst=true。

C. 测试

HomeFeedController

  • A 挂起 → B 成功 → A 成功:A/B loaded 均为 true,切回 A 立即有数据。
  • 同频道旧失败响应不得覆盖新成功响应。
  • 无在飞请求时 loadingFirstPage=false。
  • 永不返回的请求在注入超时后结束 loading、写 lastError、loaded=true。
  • 失败频道再次 select 自动重试。
  • loadMore 失败保留原有 hasMore/cursor。

PlayerLogic

  • 连续 5 次 updateFeed,最终 queue/session 对应最后一次列表。
  • 空 → 非空会创建 session 并 select 第 0 个。
  • 频道变化时相同 id 列表也回到第 1 个。

门禁:

  • dart analyze lib test
  • flutter test --no-pub
  • flutter build apk --debug

风险与控制

  1. 跨频道响应写回缓存必须与同频道 seq 校验同时存在;前者解决缓存丢失,后者解决同频道旧请求覆盖新结果。
  2. Player session 替换以 revision 作为唯一有效性判断,避免旧 close/select 回调干扰新 session。
  3. 空队列期间不创建 PlaybackSession;恢复非空时重新创建并起播。
  4. 不改后端、ReelShortWeb、specs;不安装或操作真机。

Git

  • 提交:fix(home): 修复频道快速切换卡 loading
  • --no-ff 合回 ReelShort develop 并 push。
  • 作者:Zhou Weidong <502333560@qq.com>;禁止 git add -A。