RecyclerView适配器getFilter()过滤后点击空白触发点击事件及数组越界问题
问题原因
这个问题是多个错误叠加导致的,不属于过滤逻辑的正常表现:
- 点击判断逻辑顺序错误:你在
ViewHolder的onClick方法中,先通过位置读取数组数据,才判断位置是否有效,当位置超出当前数组长度时就会触发越界崩溃。 - 过滤数据源未初始化:你代码里的
itemsFull是用来存储全量数据供过滤使用的,但你初始化时只创建了空列表,没有复制构造函数传入的初始数据,过滤逻辑本身存在隐患。 - RecyclerView布局与配置冲突:你给RecyclerView设置了
setHasFixedSize(true),同时布局中用了wrap_content作为高度。setHasFixedSize(true)会告诉RecyclerView内容变化不会影响自身宽高,当过滤后条目数量减少时,RecyclerView不会重新测量布局,之前渲染的多余条目ViewHolder没有被回收,仍然留在布局的空白区域,点击这些区域就会触发旧条目的点击事件。
修复方案
1. 修正点击事件的判断顺序
调整ViewHolder中onClick的逻辑,先校验位置合法性再读取数据:
override fun onClick(v: View?) { val position: Int = absoluteAdapterPosition // 先判断位置是否合法,再读取数组内容 if (position != RecyclerView.NO_POSITION && position < items.size) { val currentItem = items[position] val item = currentItem.itemName val definition = currentItem.itemDefinition listener.onItemClick(item,definition,currentItem) } }
2. 初始化全量过滤数据源
给itemsFull正确赋值,保证过滤逻辑能拿到全量数据:
class RecyclerViewAdapter(private var items: ArrayList<Item>, private val listener: OnItemClickListener) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>(), Filterable { // 初始化时复制传入的初始列表到全量数据源 private var itemsFull = ArrayList(items)
3. 调整RecyclerView的配置
- 布局文件中把
searchRecyclerView的高度改为match_parent,它的父布局CardView已经撑满剩余区域,用match_parent可以避免测量异常:
<androidx.recyclerview.widget.RecyclerView android:id="@+id/searchRecyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="none" tools:listitem="@layout/item"/>
- Fragment中删除
mRecyclerView2.setHasFixedSize(true)这行代码,你需要动态修改条目数量,不需要开启固定尺寸优化。
做完以上修改后,点击空白区域的异常触发和崩溃问题都会解决。
内容的提问来源于stack exchange,提问作者pepper90
相关产品推荐
相关产品推荐

