我们在使用RecyclerView的时候,总是不可避免的获取其ItemView的位置来实现各种各样的需求:
RecyClerView也提供了获取位置的几种方法,
onBindViewHolder(holder: ViewHolder, position: Int)
getAdapterPosition
getBindingAdapter
getAbslouteAdapterPosition
getLayoutPosition
通常我们会在onBindViewHolder中通过position参数绑定数据和视图,如果我们在这里使用position参数来处理点击事件会出现一些问题,
我们在布局加上一个删除列表的第一项数据功能。
这时候点击每一项弹出对应的position
我连续4次点击"删除第一项"按钮,这时候点击"第4"这一个Itme时候,应该要更新positon弹出点击了0 但是弹出点击了4.说明还是以前的位置。这就是在onBindViewHolder中直接使用position参数设置点击事件可能引发的问题。
其实原因很简单:使用notifyItem一系列的方法来删除,添加,更改我们RecyclerView的数据的任何一条数据,RecyclerView并不会调用所有Item的onBindViewHolder方法更新Item的位置,它只会更新notifyItem的位置就导致了显式的数据和实际数据的Position对应不上的问题。
官网建议使用getBindingAdapterPosition。
getAdapterPosition已经废弃了,这个方法在 Adapter 嵌套Adapter 的情况下会带来歧义
接下来看下getAbsoluteAdaptionPosition
这个方法是相对于RecyclerView的。
MergeAdapter这个在recyclerView1.2.0之后叫ContactAdapter,可以连接多个Adapter。相当于以前多种样式布局getItemViewType方案
getBindingAdapterPosition将会返回该ViewHolder相对于它绑定的Adapter的位置
getAbsoluteAdapterPosition将会返回该ViewHolder相对于RecyclerView的位置。
下面我们再来聊一下getLayoutPosition
顾名思义就是获取该ViewHolder在实际布局中的位置, RecyclerView 将布局策略委托给LayoutManager布局管理器。当开发者调用notifyData一系列方法通知RecyclerView刷新UI时,Ui并不会马上刷新,而是通过布局管理器更新布局,这个过程就需要时间上的等待,当然这个等待时间很小(不超过16ms的一般),从感官上看getLayoutposition和getAbsoluteAdapterPosition十分接近,
getAbsoluteAdapterPosition将会返回该ViewHolder相对于RecyclerView的位置。
而getLayoutposition返回的是该ViewHolder相对于ViewHolder相对于RecyclerView实际布局的绝对位置。
对于Layout的position,在notifyItemInserted之后,Layout不能马上获取到新的position,因为布局还没更新(需要<16ms的时间刷新视图)。
所以对于上面那个场景,我们在获取用户点击位置的时候,使用getLayoutPosition可能效果更好,这样可以确保用户点击的始终是他看到的那个数据。