【发布时间】:2017-09-18 16:28:54
【问题描述】:
我有一个带有 LinearLinearManager 的 RecyclerView。我的方法addItems()从网上下载数据,然后像这样一个接一个地添加10个项目:
itemIds.add(id);
listAdapter.notifyItemInserted(itemIds.size() - 1);
我在activity启动和用户滚动到(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?
编辑:在测试了不同的item size后,我发现Recyclerview总是想在这个位置加载item:
<position when reload request was started> + 2 * <reloaded item size>
这当然总是超出列表的总大小。
【问题讨论】:
-
你能分享你的适配器的基本版本吗?一开始你有10个项目,当你到达第7个项目时,你加载更多+10个项目,对吧?
-
确实如此。适配器仅将列表大小作为 itemcount 返回,并且具有正常的创建和绑定功能,我认为这与此问题无关。
标签: android scroll android-recyclerview indexoutofboundsexception