RecyclerView.ViewHolder-getLayoutPosition与getAdapterPosition


87

由于新的支持库版本(22.x暂时)的getPosition()的方法RecyclerView.ViewHolder类已被否决代替的主题中提到的方法。我阅读文档并没有真正的区别。有人可以解释外行用语的区别吗?

我有以下用例-我给适配器一个List,并且还希望能够为每个列表项关联额外的信息。我有一个位置到外部的映射,该映射可供持有者使用,以便他们可以获取自己的额外职位并对其进行处理。在持有人中,我应该使用哪种方法?

切换索引0和1的列表项时,持有者的位置会发生什么?方法返回什么?

Answers:


114

这是一个棘手的情况,很抱歉文档不够。

当适配器的内容发生更改(并且您调用notify***())时,RecyclerView会请求一个新的布局。从那时起,直到布局系统决定计算新的布局(<16 ms),由于布局尚未反映适配器的更改,因此布局位置和适配器位置可能不匹配。

在您的用例中,由于您的数据与适配器的内容有关(并且我假设数据与适配器的更改同时发生了更改),因此您应该使用adapterPosition

但是,请注意,如果正在调用notifyDataSetChanged(),因为它会使所有内容无效,因此在计算下一个布局之前,RecyclerView才知道ViewHolder的适配器位置。在这种情况下,getAdapterPosition()将返回RecyclerView#NO_POSITION-1)。

但是可以说,如果您已调用notifyItemInserted(0)getAdapterPosition()以前位于位置的ViewHolder的01立即开始返回。因此,只要分派细粒度的通知事件,您就始终处于良好状态(即使尚未计算新的布局,我们也知道适配器的位置)。

再举一个例子,如果您在用户点击时执行某项操作,如果getAdapterPosition()返回NO_POSITION,则最好忽略该点击,因为您不知道用户点击了什么(除非您有其他机制,例如,稳定的ID来查找项目)。

当布局位置合适时进行编辑

假设您正在使用LinearLayoutManager并且要访问当前单击的项目上方的ViewHolder。在这种情况下,您应该使用布局位置将其放置在上方。

mRecyclerView.findViewHolderForLayoutPosition(myViewHolder.getLayoutPosition() - 1)

您必须使用布局位置,因为它与用户当前在屏幕上看到的内容匹配。


1
我玩了一下,结果发现getAdapterPosition()方法总是对我返回-1。我对其进行了调试,原因是该方法中的代码(最终ViewParent parent = itemView.getParent(); if(!(RecyclerView的父实例)){return -1;}始终进入if块,即回收者视图不是我的单元格视图的父级,怎么回事?创建持有人的代码是:return MyViewHolder(LayoutInflater.from(viewGroup.getContext())。inflate(R.layout.test_list_item,viewGroup,false)); (继续另一评论。)
wujek 2015年

当我更改代码以调用inflate(R.layout.test_list_item,viewGroup,true); (请注意,“附加到根目录”为true),Android抛出:java.lang.IllegalStateException:指定的子代已经有一个父代。您必须先在孩子的父母上调用removeView()。那么用正确连接到回收者视图的视图创建视图持有人的正确方法是什么?奇怪的是,即使getAdapterPosition()由于父级为null而返回-1,其他所有工作都很好。
wujek 2015年

1
布局充气器中的布尔参数为“ addToParent”。它必须为false,因为LayoutManager负责添加它。我认为您是在onBind中调用getAdapterPosition,您已经通过了该职位。从技术上讲,视图持有者代表onBind返回后的位置。顺便说一句,我们已经更新了getAdapter position以返回一个有效位置(如果可能的话),即使它已分离,也将很快释放。
yigit 2015年

没错,我在onBind中调用getAdapterPosition。在这种情况下,我该怎么办,我确实需要获得一些影响某些视图状态的信息。在这种情况下调用getLayoutPosition可以吗?
wujek 2015年

5
您应该使用传递给onBind方法的position参数。
yigit 2015年

2


为了争论的差异(一个或多个)getAdapterPosition()getLayoutPosition()和也position; 我们会注意到以下情况:

1.方法中的position参数onBindViewHolder()

我们可以使用position将数据绑定到视图,可以使用position参数来完成此操作,但是使用position参数来处理用户点击不是可以的,如果使用它,您将看到一条警告,告诉您“不要将其position视为固定并holder.getAdapterPosition()改为使用”。

2 . getAdapterPosition()

此方法始终包含适配器的更新位置holder。这意味着,每当您单击某个项目时,您都会向适配器询问有关它的信息position。因此您将获得有关适配器逻辑的最新信息。

3 . getLayoutPosition()

有时,需要position根据更新的布局(用户现在看到的最后一个通过的布局)来查找,例如:如果用户要求提供第三个position他可以看到并且您使用swipe/dismiss表示项目或应用任何动画或装饰物品,最好使用getLayoutPosition()而不是getAdapterPosition(),因为您将始终确保您根据最新通过的布局来处理物品的位置。


有关此的更多信息;看这里。。。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.