安卓:RecyclerView.Adapter不能按预期工作

4
我的问题与@Richard的问题直接相关,他和我希望RecyclerView.Adapter中的onBindViewHolder()方法能像他们预期的那样被调用。

我发现在我的数据集(9个CardViews,向下滚动)到达末尾时,该方法被正确调用,但是当我尝试向上滚动回到顶部时,它不再被调用。实际的问题是,我在这里对数据集进行更改并调用notifyDataSetChanged(),但由于这种奇怪的行为(对我来说),我的修改没有在应该发生的时候生效。

我附加的图片想要说明:

  • 我到达了Rec.View的底部(cardView - Supine:一切正常);
  • 处理完全或部分显示的卡片没有问题(Supine,Gerund和Participle);
  • 但是当我到达完全被遮挡的第一张卡片视图时,onBindViewHolder()不再被调用,我可以从调试中看到与适配器链接的数据集是“Supine”,这里是:Supine cardView已显示出来。

从RecyclerView底部向上滚动--抱歉质量不佳

我认为这正是Richard在他的问题中面对的确切问题,因此我尝试了他完全相同的解决方案:我在Adapter的构造函数中强制将setHasStableIds()设置为true,

public CardAdapter(List<Object> items){
    this.items = items;
    adapterList = new ArrayList<String>();
    formAdapt = new ConjFormAdapter(adapterList);
    itemMap = new HashMap<Object, Long>();
    setHasStableIds(true);
}

这里的itemMap是我在活动中实现的一个Map,用于设置数据集的唯一ID。

我通过以下方式重写了getItemId()方法:

public long getItemId(int position) {
    Object item = items.get(position);
    return itemMap.get(item);
}

但是从图片中可以看到,我仍然得到了这个结果:有什么想法,请?

编辑

在我的活动中实现itemMap:

for(int i=0, j=0; i<conj_items.size(); i++, j++)
            conjAdapter.getItemMap().put(conj_items.get(i), (long) j);

这里的conj_items是我传递给适配器的ArrayList。


1
事实上,我已经尝试过那个解决方案,但没有任何改变...请问你能给我一个“实际ID”的例子吗?我认为这些与@ Selvin提到的“真实稳定ID”是一样的! - Massimo Baldrighi
现在先不管我写的数据集是对象列表(我刚意识到这不是必要的),假设我的项目只是ArrayLists<String>(对于GIF中所示的Rec.View部分已经是真实的了)。而且,我用来构建整个应用程序的原始数据只来自数据库。无论如何,你告诉我问题肯定是ID“不太稳定”,是吗?关于你之前的评论,我不需要比较这些项目。 - Massimo Baldrighi
我有同样的问题,您解决了这个问题吗? - user3402040
@delive:不幸的是,我不得不把这个项目搁置一段时间,所以我没能解决这个问题。不过我决定尝试一下 dexafree 的 MaterialListView 项目。我在其他应用中使用它时效果很好!链接 - Massimo Baldrighi
我也遇到了这个问题。如果启用stableIDs,请确保在getItemId()方法实现中返回唯一的长整型值。否则,它将无法工作,并且onBind不会为视图调用。 - Beemo
显示剩余6条评论
2个回答

7
当你使用setHasStableIds(true)时,你必须实现getItemId(int position)方法并返回position。你当前的代码中setHasStableIds(true)只是告诉适配器这个位置的项目不会改变,适配器无需再次调用onBindViewHolder来绑定该位置的数据。

1
除非你知道列表项(更确切地说,它们的“标识”)在更新期间不会改变,否则不建议使用“return position”。如果可能会添加、删除或移动新项目,则此方法将无法正常工作。相反,你应该使用该项的唯一标识符。 - User

0
我遇到了同样的异常,但实际上是由不同的问题引起的。在尝试了setHasStableIds(true)setLayoutTransition(null)后都没有成功之后,我意识到我在onCreateViewHolder中将视图添加到父级(这是不应该做的,因为适配器会为您处理)。我删除了它,问题得到了解决。
@Override
public TopTrayIconAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    DMImageView icon = new DMImageView(mContext);
    LinearLayout.LayoutParams faceParams = new LinearLayout.LayoutParams(ICON_WIDTH, ICON_WIDTH);
    faceParams.gravity = Gravity.CENTER;
    faceParams.leftMargin = 15;
    faceParams.rightMargin = 15;

    parent.addView(icon, faceParams);  <- THIS WAS THE ISSUE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接