ListView转RecyclerView:实现双ViewHolder及解决滚动视图错乱问题
解决RecyclerView滚动时视图错乱的问题
你遇到的问题是典型的RecyclerView ViewHolder复用导致的状态残留,再加上原代码里的循环逻辑有冗余且会引发错误,咱们一步步来修复:
核心问题分析
- 视图状态未重置:RecyclerView会复用滑出屏幕的ViewHolder,如果你没有在
onBindViewHolder里先还原视图的默认状态,之前item的可见性设置会被带到新的item上,直接导致滚动时显示错乱。 - 冗余的循环逻辑:你用了一个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
相关产品推荐
相关产品推荐

