我有RecyclerView
,显示List
个分页元素。
最初列表的大小为n
,但是当您接近顶部时,需要加载更多元素,并且适配器将获取p
元素(并且列表将增大到{ {1}})
我这样做的方法是获取n + p
元素,如果p
为0,则将其添加到onBindViewHolder
内的列表中:
position
这在大多数情况下都可以正常工作。这就是问题所在:
假设可以提取class MyAdapter : RecyclerView.Adapter<MyViewHolder>() {
val elements: List<Any> = emptyList()
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
//viewholder binding code
if (position == 0) {
loadPreviousPage()
}
}
private fun loadPreviousPage() {
val newElements = someCall() //List of size p
elements.addAll(0, newElements)
}
}
个总元素(3个页面),这意味着适配器以3p
元素开始,然后调用0
,loadPreviousPage
增长到elements
,p
,最后增长到2p
。我看到的是该列表正在更新,但3p
不是。
示例:
如果View
,我的p = 3
,每个分页电话看起来像:
elements
但在我的I : g h i
II : d e f g h i
III : a b c d e f g h i
中,我看到类似RecyclerView
如果我滚动以便不正确的i d e d e f g h i
退出屏幕并向后滚动,一切正常,View
看起来与预期一样(RecyclerView
)
我不确定究竟发生了什么,但这种行为(甚至是a b c d e f g h i
的状态)是一致且可重复的。我怀疑由于列表大小正在发生变化,因此在向RecyclerView
添加m
元素之后,位于p
位置的元素不再处于同一位置,并且RecyclerView
没有已被通知此事。但是,我无法在notiyItemChanged
中拨打loadPreviousPage
,因为它是在布局本身时从onBindViewHolder
调用的。
我该如何解决这个问题?任何帮助将不胜感激。
答案 0 :(得分:0)
您的代码正在修改支持适配器的数据结构,而不通知适配器其数据集已被修改:
private fun loadPreviousPage() {
val newElements = someCall() //List of size p
elements.addAll(0, newElements)
}
正如您所说,您无法调用任何notifyDataSetChanged()
及相关方法,因为您可以获得:
java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling
在我看来,处理此问题的正确方法是使用loadPreviousPage()
将来电延迟到Handler.post()
。这使您无法调用notifyXyz
方法的非法窗口,但会使您保持主线程,以便您可以调用notifyXyz
。
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
if (position == 0) {
Handler().post { loadPreviousPage() }
}
}
private fun loadPreviousPage() {
val newElements = someCall() //List of size p
elements.addAll(0, newElements)
notifyItemRangeInserted(0, newElements.size);
}
在其他帖子上调用loadPreviousPage()
后,您可以自由使用notifyXyz
方法。
PS:似乎只是在绑定调用中执行此操作会立即加载所有可用页面。一旦你&#34;插入&#34;一个新页面,该视图持有者将再次绑定,这似乎会触发另一个页面加载。也许你已经解决了这个问题,但我想把它搞定。但是,它似乎超出了你的问题的范围,所以我没有在这里解决它。