You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发:如何避免RecyclerView Adapter对已加载条目重复发起Google Books API请求

问题根因与修复方案
  • 当前实现会触发过量接口请求的核心原因:
    • 所有Firestore查询、Google Books API请求的逻辑完全耦合在onBindViewHolder的绑定流程里,没有为每个条目标记是否已经完成过数据加载,只要视图重新触发绑定,就会无条件发起新请求
    • 给所有ViewHolder设置了holder.setIsRecyclable(false),直接关闭了RecyclerView的视图复用机制,条目滚动出屏幕再回滚进入可视区时,一定会重新跑一遍完整的绑定流程,进一步放大了重复请求的问题
  • 以下是能实现“已加载条目回滚时不重复发请求”的落地方案:

1. 在Adapter层增加两级状态缓存

由于ViewHolder本身是会被回收复用的,把加载状态存在ViewHolder里会随视图回收丢失,必须把加载状态、缓存数据存在Adapter的全局成员中:

// 已成功拉取完成的BookID集合,命中后直接读缓存,不发新请求
private final Set<String> loadedCompletedIds = new HashSet<>();
// 正在发起请求的BookID集合,命中后不重复触发请求
private final Set<String> loadingIds = new HashSet<>();
// 缓存已拉取完成的条目解析数据,绑定时直接读取填充UI
private final Map<String, Object> itemDataCache = new HashMap<>();

2. 改造bind流程,优先查缓存再发请求

拿到当前条目的BookID后,按顺序做判断分支:

  1. 先查loadedCompletedIds,如果存在对应ID:直接从itemDataCache取出已缓存的数据更新UI,完全跳过网络/数据库请求的逻辑
  2. 再查loadingIds,如果ID已经在加载队列中:不重复发起请求,等之前的请求回调拿到结果后自动更新UI即可
  3. 两个集合都未命中时,再正式发起Firestore查询或者Google Books API请求,发起请求前先把当前BookID加入loadingIds集合
  4. 请求结果回调触发时:先把BookID从loadingIds中移除;如果请求成功,就把BookID加入loadedCompletedIds,解析后的结果存入itemDataCache,再执行UI更新

注意:请求回调中更新UI前,需要校验当前ViewHolder实际绑定的BookID和发起请求时的BookID是否一致,避免ViewHolder被复用到其他条目时,旧请求返回错绑数据。

3. 清理冗余的代码逻辑

  • 移除没有特殊业务需求的holder.setIsRecyclable(false)设置,恢复RecyclerView正常的视图复用能力,减少无意义的重复绑定
  • 把FirebaseFirestore、FirebaseAuth的单例初始化从每次执行的bind逻辑中,移到Adapter构造函数中做一次全局初始化,避免每次绑定时重复取单例的冗余操作

4. 适配场景的小优化

如果列表总长度在百条以内,现有缓存策略完全不会产生过多内存占用;如果列表长度较大,可以给缓存集合设置容量上限,超限时清理最早加载的缓存条目,避免内存溢出。


内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.24 20:45:05