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

Android Studio中RecyclerView用ListAdapter遇IndexOutOfBoundsException崩溃问题

ListAdapter提交空列表崩溃的原因分析

核心矛盾:自定义数据状态与ListAdapter内部状态不一致

你的Adapter存在关键问题:手动维护size变量控制条目数量和视图类型,却忽略了ListAdapter本身依赖currentList管理数据源的核心机制,导致数据状态和视图状态出现冲突。

具体问题拆解

  1. getItemCount的错误重写
    当size=0时,你让getItemCount返回1(用于显示空布局),但此时ListAdapter内部的currentList是空的。submitList方法会基于新旧currentList执行DiffUtil差异计算,这就出现了「Adapter告诉RecyclerView有1个条目,但实际数据源无数据」的矛盾。
    调用无回调的submitList(new ArrayList(myNewList))时,DiffUtil会按内部空列表计算更新操作,RecyclerView却按照getItemCount的结果去绑定视图,最终触发位置越界——因为实际数据源没有对应位置的数据。

  2. 带notifyDataSetChanged的回调能避免崩溃的原因
    在submitList的回调里调用adapter.notifyDataSetChanged()时,这个操作会强制RecyclerView完全刷新所有视图,跳过DiffUtil的局部更新逻辑。相当于让RecyclerView直接重新读取getItemCount和getItemViewType的结果,暂时掩盖了「数据源和条目数量不一致」的问题,但这只是治标不治本的临时方案。

错误日志对应解释

日志中的IndexOutOfBoundsException,是因为RecyclerView根据getItemCount认为存在1个条目,但ListAdapter内部的currentList是空的,导致视图持有者的位置计算混乱,超出了实际数据源的范围。

正确修复方案

  1. 移除手动维护的size变量,直接用ListAdapter提供的getCurrentList()判断数据状态:
    // 删除setSize方法
    @Override
    public int getItemCount() {
        // 列表为空时返回1(空布局),否则返回实际条目数
        return getCurrentList().isEmpty() ? 1 : getCurrentList().size();
    }
    
    @Override
    public int getItemViewType(int position) {
        // 空布局场景下position固定为0
        if (getCurrentList().isEmpty()) {
            return TYPE_EMPTY;
        } else {
            return TYPE_ONE;
        }
    }
    
  2. ViewModel观察代码简化:无需手动设置size,直接提交列表即可:
    customerRelationObserver = list -> {
        adapter.submitList(list);
    };
    
  3. 更优雅的空布局实现(可选):推荐使用外部空视图机制——在布局中添加空视图(如TextView),列表为空时显示空视图、隐藏RecyclerView;列表有数据时隐藏空视图、显示RecyclerView。这种方式不需要在Adapter中特殊处理条目数,逻辑更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:45:35