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

Android RecyclerView分页快速点击触发fromIndex大于toIndex异常如何解决

问题根因

你虽然在setAdapter里做了按钮可见性的控制,但Android的View可见性更新不是同步生效的,用户快速点击时,按钮隐藏的逻辑还没执行,点击事件就已经触发多次,导致CURRENT_PAGE超出合法范围(小于1或者大于TOTAL_PAGE),最终计算出来的FROM大于TO,触发subList的参数非法异常。


修复方案

1. 点击事件增加边界前置校验(必改)

在修改CURRENT_PAGE之前先判断是否已经是边界值,不符合条件直接拦截点击事件,这是最核心的修复:

butNext.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 前置校验:已经是最后一页直接拦截
        if (CURRENT_PAGE >= TOTAL_PAGE) {
            return;
        }
        CURRENT_PAGE = CURRENT_PAGE+1;
        FROM = (CURRENT_PAGE-1)* Constant.ITEM_PER_PAGE;
        TO = FROM + Constant.ITEM_PER_PAGE;
        if(TO>TOTAL){
            TO = TOTAL;
        }
        setAdapter(FROM,TO);
    }
});
butPrev.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 前置校验:已经是第一页直接拦截
        if (CURRENT_PAGE <= 1) {
            return;
        }
        CURRENT_PAGE = CURRENT_PAGE-1;
        FROM = (CURRENT_PAGE-1) * Constant.ITEM_PER_PAGE;
        TO = FROM + Constant.ITEM_PER_PAGE;
        if(TO>TOTAL){
            TO = TOTAL;
        }
        setAdapter(FROM,TO);
    }
});

2. 增加subList参数兜底校验

在调用subList之前先对参数做合法性校验,避免其他异常场景也触发崩溃:

private void setAdapter(int From, int To) {
    textPageCount.setText(CURRENT_PAGE +"/" +TOTAL_PAGE);
    butPrev.setVisibility((CURRENT_PAGE ==1) ? View.INVISIBLE : View.VISIBLE);
    butNext.setVisibility((CURRENT_PAGE == TOTAL_PAGE) ? View.INVISIBLE : View.VISIBLE);
    progressBar.setVisibility(View.GONE);

    // 兜底参数校验
    int listSize = Constant.arrayListCategories.size();
    From = Math.max(From, 0);
    To = Math.min(To, listSize);
    if (From >= To) {
        // 参数非法直接返回,避免崩溃
        setEmpty();
        return;
    }

    ArrayList<ItemCategory> arraylistsub = new ArrayList<>(Constant.arrayListCategories.subList(From, To));
    adapterCat = new AdapterCat(arraylistsub);
    recyclerView.setAdapter(adapterCat);
    setEmpty();
}

可选优化:增加点击防抖

如果要彻底避免快速点击的问题,可以给按钮加500ms防抖逻辑,短时间内只响应一次点击:

// 类中增加变量记录上次点击时间
private long lastClickTime = 0;

// 点击事件中增加防抖判断
butNext.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastClickTime < 500) {
            return;
        }
        lastClickTime = currentTime;
        // 原有逻辑
        if (CURRENT_PAGE >= TOTAL_PAGE) {
            return;
        }
        CURRENT_PAGE = CURRENT_PAGE+1;
        FROM = (CURRENT_PAGE-1)* Constant.ITEM_PER_PAGE;
        TO = FROM + Constant.ITEM_PER_PAGE;
        if(TO>TOTAL){
            TO = TOTAL;
        }
        setAdapter(FROM,TO);
    }
});

性能优化建议

当前每次分页都重新创建Adapter、重新绑定RecyclerView的性能损耗较大,建议复用同一个Adapter,仅更新Adapter内部的数据集后调用notifyDataSetChanged即可,分页切换的流畅度会明显提升。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 17:06:04