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

如何在带筛选的RecyclerView中始终显示10条数据(规避索引越界)

解决RecyclerView筛选时仅显示10条数据的索引越界问题

嘿,我碰到过类似的问题,其实核心原因很简单——你应该是在筛选后不管结果有多少,都硬返回10作为getItemCount()的结果,对吧?当筛选出来的数据不足10条时,RecyclerView去访问超出结果长度的索引,自然就抛出IndexOutOfBoundsException了。结合你用Realm的场景,给你两个靠谱的实现方案:

方案一:动态计算返回的item数量

核心思路是让getItemCount()返回筛选结果数量和10的较小值,确保永远不会请求超出实际数据范围的索引:

  1. 在适配器中维护两个RealmResults对象:一个存原始全量数据,一个存筛选后的结果
  2. 实现筛选方法,根据输入更新筛选结果集
  3. 重写getItemCount()时取两者的最小值
  4. 在绑定ViewHolder时直接从筛选结果集取数据

修改后的关键代码片段:

public class RealmAutoCompleteAdapter extends RecyclerView.Adapter<RealmAutoCompleteAdapter.ProductViewHolder> {
    private Realm realm;
    private RealmResults<FieldsItem> originalFullResults; // 原始283条全量数据
    private RealmResults<FieldsItem> currentFilteredResults; // 筛选后的结果
    private RealmChangeListener<RealmResults<FieldsItem>> realmChangeListener;

    // 构造方法初始化全量数据
    public RealmAutoCompleteAdapter(Realm realm, RealmResults<FieldsItem> fullResults) {
        this.realm = realm;
        this.originalFullResults = fullResults;
        this.currentFilteredResults = fullResults; // 初始默认显示全量的前10条
        setupRealmListener();
    }

    // 外部调用的筛选方法(比如在TextView的TextWatcher中触发)
    public void performFilter(String searchQuery) {
        if (TextUtils.isEmpty(searchQuery)) {
            // 空查询时回到全量数据
            currentFilteredResults = originalFullResults;
        } else {
            // 根据输入执行Realm查询,匹配你需要筛选的字段
            currentFilteredResults = realm.where(FieldsItem.class)
                    .contains("targetFieldName", searchQuery, Case.INSENSITIVE)
                    .findAll();
        }
        notifyDataSetChanged(); // 更新列表
    }

    private void setupRealmListener() {
        // 监听原始数据变化,自动更新列表
        realmChangeListener = results -> notifyDataSetChanged();
        originalFullResults.addChangeListener(realmChangeListener);
    }

    @Override
    public int getItemCount() {
        // 关键:永远返回筛选结果数量和10的较小值
        return Math.min(currentFilteredResults.size(), 10);
    }

    @Override
    public void onBindViewHolder(@NonNull ProductViewHolder holder, int position) {
        // 直接从筛选结果集中取数据,position不会越界
        FieldsItem item = currentFilteredResults.get(position);
        holder.itemTextView.setText(item.getTargetField());
        // 其他绑定逻辑...
    }

    // ProductViewHolder定义和其他方法省略...
}

方案二:查询阶段直接限制结果数量(更高效)

既然你只需要最多10条数据,不如直接在Realm的查询语句中加上limit(10),这样筛选结果集本身最多只有10条,getItemCount()直接返回结果集的size即可,从根源避免越界:

修改筛选方法中的查询逻辑:

public void performFilter(String searchQuery) {
    if (TextUtils.isEmpty(searchQuery)) {
        currentFilteredResults = realm.where(FieldsItem.class)
                .limit(10) // 全量时也只取前10条
                .findAll();
    } else {
        currentFilteredResults = realm.where(FieldsItem.class)
                .contains("targetFieldName", searchQuery, Case.INSENSITIVE)
                .limit(10) // 筛选结果最多返回10条
                .findAll();
    }
    notifyDataSetChanged();
}

// 此时getItemCount()可以直接返回结果集的size
@Override
public int getItemCount() {
    return currentFilteredResults.size();
}

注意事项

  • 记得在适配器销毁时移除Realm的监听器,避免内存泄漏
  • 如果需要支持Realm的自动数据更新,确保筛选后的结果集也能正确监听变化(方案一中的监听器已经覆盖了原始数据变化的场景)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:41:39