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

ListView转RecyclerView:实现双ViewHolder及解决滚动视图错乱问题

解决RecyclerView滚动时视图错乱的问题

你遇到的问题是典型的RecyclerView ViewHolder复用导致的状态残留,再加上原代码里的循环逻辑有冗余且会引发错误,咱们一步步来修复:

核心问题分析

  1. 视图状态未重置:RecyclerView会复用滑出屏幕的ViewHolder,如果你没有在onBindViewHolder里先还原视图的默认状态,之前item的可见性设置会被带到新的item上,直接导致滚动时显示错乱。
  2. 冗余的循环逻辑:你用了一个for循环来判断手机号是否在matchingContacts里,但matchingContacts.contains()本身就能直接完成存在性判断,循环完全没必要——而且循环过程中每次不匹配就设置check为GONE,会导致逻辑混乱。

修复后的代码

直接修改你的onBindViewHolder方法,同时调整逻辑:

@Override
public void onBindViewHolder(final PopulistoContactsAdapter.ViewHolder viewHolder, final int position) {
    final SelectPhoneContact selectPhoneContact = theContactsList.get(position);
    
    // 绑定基础数据
    viewHolder.title.setText(selectPhoneContact.getName());
    viewHolder.phone.setText(selectPhoneContact.getPhone());
    
    // 关键:先重置两个控件的可见性为默认状态(VISIBLE),彻底避免复用残留
    viewHolder.invite.setVisibility(View.VISIBLE);
    viewHolder.check.setVisibility(View.VISIBLE);
    
    // 简化判断逻辑:直接用contains判断,不需要循环遍历
    boolean isMatching = matchingContacts.contains(selectPhoneContact.getPhone());
    if (isMatching) {
        // 匹配联系人:隐藏邀请按钮,保留复选框
        viewHolder.invite.setVisibility(View.GONE);
    } else {
        // 非匹配联系人:隐藏复选框,保留邀请按钮
        viewHolder.check.setVisibility(View.GONE);
    }
}

额外优化建议

为了让contains判断更高效,建议把matchingContacts从ArrayList改成HashSet——HashSet的contains方法时间复杂度是O(1),比ArrayList的O(n)快很多,尤其是当匹配列表数据量较大时:

在Adapter的构造方法里修改:

// 把ArrayList替换为HashSet
HashSet<String> matchingContacts = new HashSet<>();

// 添加数据的方式不变
matchingContacts.add("+3531234567");
matchingContacts.add("+3536789012");
matchingContacts.add("+3530987654");
matchingContacts.add("+3538765432");

这样修改后,滚动时就不会再出现视图错乱的问题了——每次绑定新数据时都会先还原控件的默认状态,再根据当前item的条件设置正确的可见性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:09:16