RecyclerView ViewHolder getAdapterPosition()返回NO_POSITION(-1)

最近项目中频繁点击recycleView的click事件,抛出越界异常,显示index = -1

java.lang.ArrayIndexOutOfBoundsException: length=1512; index=-1
at java.util.ArrayList.get(ArrayList.java:439)

解决方式:

  • 在viewHolder持有数据源,通过数据源在List中的位置来获取position
  • 在用到position的地方去判断是否为-1,若为-1,则 return;

分析:
查看getAdapterPosition()源码(现在这个方法被废弃了,用getAbsoluteAdapterPosition()来替代)

int getAdapterPositionInRecyclerView(ViewHolder viewHolder) {
        if (viewHolder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID
                | ViewHolder.FLAG_REMOVED | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)
                || !viewHolder.isBound()) {
            return RecyclerView.NO_POSITION;
        }
        return mAdapterHelper.applyPendingUpdatesToPosition(viewHolder.mPosition);
    }

当viewHolder处于FLAG_REMOVED 或者FLAG_ADAPTER_POSITION_UNKNOWN状态时,会返回NO_POSITION
官方文档里关于getAdapterPosition ()是这样说的:

Returns the Adapter position of the item represented by this ViewHolder.

Note that this might be different than the getLayoutPosition() if there are pending adapter updates but a new layout pass has not happened yet. //请注意,如果存在挂起的适配器更新,但尚未进行新的布局传递,则这可能与getLayoutPosition()不同。

RecyclerView does not handle any adapter updates until the next layout traversal. This may create temporary inconsistencies between what user sees on the screen and what adapter contents have. This inconsistency is not important since it will be less than 16ms but it might be a problem if you want to use ViewHolder position to access the adapter. Sometimes, you may need to get the exact adapter position to do some actions in response to user events. In that case, you should use this method which will calculate the Adapter position of the ViewHolder.

Note that if you've called notifyDataSetChanged(), until the next layout pass, the return value of this method will be NO_POSITION.

image.png

大体意思是:
layout和adapter的position会有时间差(<16ms),改变了adapter后去刷新layout,layout需要过一段时间去更新视图,在这段时间里,获取到的position是不一样的。
未notifyDataSetChanged()时,getAdapterPosition是会返回NO_POSITION(-1)。
注:建议等布局更新结束后再去获取position。

你可能感兴趣的:(RecyclerView ViewHolder getAdapterPosition()返回NO_POSITION(-1))