Android RecyclerView支持列表,其大小不断变化

时间:2018-03-06 19:17:37

标签: android android-recyclerview

我有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元素开始,然后调用0loadPreviousPage增长到elementsp,最后增长到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调用的。

我该如何解决这个问题?任何帮助将不胜感激。

1 个答案:

答案 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;一个新页面,该视图持有者将再次绑定,这似乎会触发另一个页面加载。也许你已经解决了这个问题,但我想把它搞定。但是,它似乎超出了你的问题的范围,所以我没有在这里解决它。