【问题标题】:RecyclerView.ViewHolder - getLayoutPosition vs getAdapterPositionRecyclerView.ViewHolder - getLayoutPosition 与 getAdapterPosition
【发布时间】:2015-04-16 19:23:33
【问题描述】:

自从新的支持库版本 (22.x) 以来,RecyclerView.ViewHolder 类的 getPosition() 方法已被弃用,以代替主题中提到的方法。我并没有真正从阅读文档中得到区别。 有人可以用外行的话解释一下区别吗?

我有以下用例——我给我的适配器一个List,并且还希望能够为每个列表项关联额外的信息。我有一个位置到额外的映射,该映射可供持有者使用,这样他们就可以为他们的位置获取额外的东西并用它做事。在持有人中,我应该使用哪种方法?

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

【问题讨论】:

    标签: android android-recyclerview


    【解决方案1】:

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

    当适配器内容改变时(并且你调用notify***())RecyclerView 请求一个新的布局。从那时起,直到布局系统决定计算新的布局(

    在您的用例中,由于您的数据与您的适配器内容相关(我假设数据与适配器更改同时更改),您应该使用adapterPosition

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

    但是假设你调用了notifyItemInserted(0),之前位于0 位置的ViewHolder 的getAdapterPosition() 将立即开始返回1。因此,只要您调度细粒度的通知事件,您就始终处于良好状态(即使尚未计算新布局,我们也知道适配器位置)。

    另一个例子,如果你在用户点击时做某事,如果getAdapterPosition()返回NO_POSITION,最好忽略那个点击,因为你不知道用户点击了什么(除非你有一些其他的机制,例如stable ids 来查找项目)。

    在布局位置合适时编辑

    假设您正在使用LinearLayoutManager 并希望访问当前单击项目上方的 ViewHolder。在这种情况下,您应该使用布局位置来获取上面的项目。

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

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

    【讨论】:

    • 我玩了一会儿,结果发现 getAdapterPosition() 方法总是在我身上返回 -1。我调试了一下,原因是方法中的代码 (final ViewParent parent = itemView.getParent(); if (!(parent instanceof RecyclerView)) { return -1; } 总是进入if块,即recycler view不是我的单元格视图的父级。怎么可能?我创建持有者的代码是: return MyViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.test_list_item, viewGroup, false)); (在另一条评论中继续。)
    • 当我将代码更改为调用 inflate(R.layout.test_list_item, viewGroup, true); (注意 'attach to root 的 true),Android 抛出:java.lang.IllegalStateException:指定的孩子已经有一个父母。您必须首先在孩子的父母上调用 removeView()。那么创建视图持有者的正确方法是什么是正确附加到回收者视图的视图?奇怪的是,即使 getAdapterPosition() 因为 parent 为 null 而返回 -1,其他一切都正常。
    • 布局充气器中的布尔参数是“addToParent”。它一定是假的,因为添加它是 LayoutManager 的责任。我认为您在 onBind 中调用 getAdapterPosition ,您已经通过了该位置。从技术上讲,视图持有者代表 onBind 返回后的那个位置。顺便说一句,我们已经更新了 getAdapter 位置以返回一个有效的位置(如果可能的话),即使它是分离的,它也会很快被释放。
    • 你说得对,我在 onBind 中调用 getAdapterPosition。在这种情况下我应该怎么做,我确实需要获得一些影响某些视图状态的信息的位置。在这种情况下调用 getLayoutPosition 可以吗?
    • 您应该使用传递给 onBind 方法的位置参数。
    【解决方案2】:

    为了争论getAdapterPosition()getLayoutPosition()position的区别;我们会注意到以下情况:

    1.positiononBindViewHolder() 方法中的参数:

    我们可以使用position 将数据绑定到视图,可以使用position 参数来执行此操作,但不能使用position 参数来处理用户点击,如果您使用了它您会看到一条警告,告诉您“不要将 position 视为已修复,而是使用 holder.getAdapterPosition()”。

    2.getAdapterPosition():

    此方法始终包含更新后的适配器位置holder。这意味着每当您单击一个项目时,您都会向适配器询问它是position。所以你会得到这个项目在适配器逻辑方面的最新位置。

    3.getLayoutPosition():

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


    有关这方面的更多信息;见here。 . .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-14
      • 2015-07-28
      • 2017-02-28
      • 1970-01-01
      • 2018-10-08
      • 1970-01-01
      • 2022-01-02
      相关资源
      最近更新 更多