我有一个带有LinearLinearManager的RecyclerView。我的方法addItems()
从互联网上下载数据,然后依次添加10个项目:
itemIds.add(id);
listAdapter.notifyItemInserted(itemIds.size() - 1);
我在活动开始时以及当用户滚动到(size-3)时调用此方法:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
if (!pending && !loadingMoreItems &&
listAdapter.getItemCount() - layoutManager.findLastVisibleItemPosition() <= 3) {
loadingMoreItems = true;
Log.d(LOG_TAG, "new data!");
addItems();
}
}
});
当我启动应用程序并滚动到位置7时,将加载新数据。但是在添加这些项目后(新项目大小为20,我检查了),我收到以下错误:
java.lang.IndexOutOfBoundsException:
Inconsistency detected. Invalid view holder adapter position
ViewHolder{9cff95d position=27 id=-1, oldPos=7, pLpos:5
scrap [attachedScrap] tmpDetached no parent}
因此,RecyclerView希望将旧位置7的ViewHolder重新用于新位置27 - 但当然,该位置不存在。
为了进行调试,我添加了一个扩展LinearLayoutManager的自定义类,它可以防止由于IndexOutOfBoundsException而崩溃:
@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没有任何作用。有没有人知道如何解决这个奇怪的位置27?
编辑:在测试了不同的商品尺寸后,我发现Recyclerview总是希望在此位置加载商品:
<position when reload request was started> + 2 * <reloaded item size>
当然,这总是超出总列表大小。
答案 0 :(得分:2)
这种情况正在发生,因为您正在向列表中添加数据,同时您在通知适配器之前尝试滚动Recyclerview。
所以当您在第7个位置后加载数据时执行此操作
mData.add(yourdata);
mAdapter.notifyDataSetChanged();
如果您将继续添加数据并继续滚动它。它会给你&#34;检测到不一致。&#34;错误。因为适配器认为只有7个项目,当你滚动它已经变成了10个没有通知adaper。
答案 1 :(得分:1)
您似乎必须使用此方法listAdapter.notifyItemRangeInserted(startPosition, itemCount);
notifyItemInserted(position)
用于仅插入一个项目。如果要插入多个项目,则必须使用notifyItemRangeInserted(position, itemCount)
您是否会使用此方法插入所有10个项目,而不是逐个添加循环并检查是否获得相同的异常?
答案 2 :(得分:0)
除了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);
}
}
由于其中的错误,在使用ListView时实现分页时需要捕获异常的块。但是Recyclerview并不需要它。
还会给你的代码一个机会,看看它到底出了什么问题。