Android 添加项后,Recyclerview将索引绑定到列表大小之外

Android 添加项后,Recyclerview将索引绑定到列表大小之外,android,scroll,android-recyclerview,indexoutofboundsexception,Android,Scroll,Android Recyclerview,Indexoutofboundsexception,我有一个回收站的经理。我的方法addItems()从Internet下载数据,然后依次添加10项,如下所示: itemIds.add(id); listAdapter.notifyItemInserted(itemIds.size() - 1); 当活动启动并且用户滚动到(大小-3)时,我调用此方法: 因此,RecyclerView希望将旧位置7的ViewHolder重新用于新位置27,但该位置当然不存在 为了进行调试,我添加了一个自定义类,扩展了LinearLayoutManager,以防止

我有一个回收站的经理。我的方法
addItems()
从Internet下载数据,然后依次添加10项,如下所示:

itemIds.add(id);
listAdapter.notifyItemInserted(itemIds.size() - 1);
当活动启动并且用户滚动到(大小-3)时,我调用此方法:

因此,RecyclerView希望将旧位置7的ViewHolder重新用于新位置27,但该位置当然不存在

为了进行调试,我添加了一个自定义类,扩展了LinearLayoutManager,以防止因IndexOutfBoundsException而崩溃:

@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
    try {
        super.onLayoutChildren(recycler, state);
    } catch (IndexOutOfBoundsException e) {
        e.printStackTrace();
    }
}
然后我的列表就完美地工作了——新的项目被平滑地添加到列表中,甚至多次,因此它会产生一个无限的列表。Logcat中只有这个小堆栈跟踪

我觉得用try/catch忽略这个IndexOutOfBoundsException是不对的,因为它实际上对catch没有任何作用。有人知道如何修复这个奇怪的位置吗

编辑:在测试了不同的项目大小后,我发现Recyclerview总是希望在此位置加载项目:

+2*


当然,它总是超出总列表大小。

看起来您必须使用此方法
listAdapter.notifyItemRangeInserted(startPosition,itemCount)

notifyItemInserted(位置)
仅用于插入一项。如果要插入多个项目,必须使用
notifyItemRangeInserted(position,itemCount)


您是否会使用此方法插入所有10项,而不是在循环中逐个添加,并检查是否得到相同的异常

除了Dinesh Bob所说的之外,我认为您的代码没有任何问题。我将在RecyclerView中发布如何实现分页:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            int visibleItemCount=linearLayoutManager.getChildCount();
            int totalItemCount=linearLayoutManager.getItemCount();
            int firstVisibleItemPosition=linearLayoutManager.findFirstVisibleItemPosition();

            if(!isPageLoading && !isLastPage)
            {
                if((visibleItemCount + firstVisibleItemPosition)>=totalItemCount)
                {
                    offset+=limit;
                    loadMoreItems(offset);
                }
            }
        }
    });
loadMoreItems继续并进行API调用,然后将这些项添加到适配器中,如下所示:

public void addAllItems(List<Item> itemList)
{
    for(Item itemRow: itemList)
    {
        this.itemList.add(itemRow);
        notifyItemInserted(this.itemList.size() - 1);
    }
}
public void addAllItems(列表项列表)
{
对于(项目行:项目列表)
{
this.itemList.add(itemRow);
notifyItemInserted(this.itemList.size()-1);
}
}
由于ListView中存在错误,在使用ListView时实现分页时,捕获异常的块是必需的。但是回收站不需要它


也会给你的代码一个机会,看看它到底出了什么问题

之所以发生这种情况,是因为您正在向列表中添加数据,同时在通知recyclerview的适配器之前尝试滚动它

所以,当您在第7位之后加载数据时,请执行此操作

mData.add(yourdata);
mAdapter.notifyDataSetChanged();

如果您将继续添加数据并继续滚动它。它将为您提供“检测到不一致性”错误。因为adapter认为只有7项,当您滚动时,它变成了10项,而adaper没有收到通知。

谢谢您的回答,但不幸的是,错误仍然存在。您可以共享适配器的基本版本吗?一开始你有10个项目,当你达到第7个项目时,你会加载更多+10个项目,对吗?没错。适配器仅将列表大小返回为itemcount,并具有正常的创建和绑定函数,我认为这与此问题无关。谢谢,您的代码与我的代码几乎相同–我切换到firstVisibleItemPosition而不是lastVisible,并使用linearLayoutManager.getChildCount()而不是adapter.getChildCount(),但是错误仍然存在。将
notifyItemInserted(…)
替换为
notifyDataSetChanged()
对我来说成功了!不知道为什么,因为
notifyItemInserted
实际上更具体,因此更好,但无论如何,感谢您的正确答案!(PS:
mAdapter.updateData(mData);
在我看来是不需要的,因为适配器和我的活动都引用了保存所有数据项的同一个列表对象。)
public void addAllItems(List<Item> itemList)
{
    for(Item itemRow: itemList)
    {
        this.itemList.add(itemRow);
        notifyItemInserted(this.itemList.size() - 1);
    }
}
mData.add(yourdata);
mAdapter.notifyDataSetChanged();