项目刚上线,bugly上面就一堆RecyclerView的越界异常.部门大佬提交一个版本的修复上去,将原来使用的position全部替换成了holder.getLayoutPosition(),还是有异常发生.无奈去看了adapter中对于getLayoutPosition()以及getAdapterPosition()的说明以及场景.
/** * Returns the position of the ViewHolder in terms of the latest layout pass. * <p> * This position is mostly used by RecyclerView components to be consistent while * RecyclerView lazily processes adapter updates. * <p> * For performance and animation reasons, RecyclerView batches all adapter updates until the * next layout pass. This may cause mismatches between the Adapter position of the item and * the position it had in the latest layout calculations. * <p> * LayoutManagers should always call this method while doing calculations based on item * positions. All methods in {@link RecyclerView.LayoutManager}, {@link RecyclerView.State}, * {@link RecyclerView.Recycler} that receive a position expect it to be the layout position * of the item. * <p> * If LayoutManager needs to call an external method that requires the adapter position of * the item, it can use {@link #getAdapterPosition()} or * {@link RecyclerView.Recycler#convertPreLayoutPositionToPostLayout(int)}. * * @return Returns the adapter position of the ViewHolder in the latest layout pass. * @see #getAdapterPosition() */
上面是getLayoutPosition的说明,大致意思是获取到新的填充数据中的位置.但是由于重新布局计算及条目动画的限制,有时候会造成最新的位置跟返回的位置可能会不匹配
/** * Returns the Adapter position of the item represented by this ViewHolder. * <p> * Note that this might be different than the {@link #getLayoutPosition()} if there are * pending adapter updates but a new layout pass has not happened yet. * <p> * 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. * <p> * Note that if you've called {@link RecyclerView.Adapter#notifyDataSetChanged()}, until the * next layout pass, the return value of this method will be {@link #NO_POSITION}. * * @return The adapter position of the item if it still exists in the adapter. * {@link RecyclerView#NO_POSITION} if item has been removed from the adapter, * {@link RecyclerView.Adapter#notifyDataSetChanged()} has been called after the last * layout pass or the ViewHolder has already been recycled. */
这个是getAdapterPosition的官方说明,这个获取到位置跟LayoutPosition在平时应该是一致的,当RecyclerView的数据源发生变化时,要进行绘制计算等操作.官方推荐处理一些用户操作时使用getAdapterPosition,但是当调用notifyDataSetChanger()时可能返回NO_POSITION(-1)
所以项目中关于position的处理暂时是用AdaperPosition获取到位置 然后进行NO_POSITION以及数据源的边缘限制之后才去分发响应逻辑操作,如果有不对的地方或者更好的办法也请大佬告知