如何避免IllegalStateException调用notifyDataSetChanged?

问题描述 投票:0回答:2

我有一个名为imageRecyclerView的水平回收视图,其中每列只包含一个ImageView。 Recycler视图的适配器类称为ImageAdapterimageRecyclerView适配器的数据集是包含URL的ArrayList字符串。 ArrayList被称为currentImageURLs

注意 - 所有这些代码的目的是一次一个地将图像加载到imageRecyclerView中。

在我的onBindViewHolder类的ImageAdapter方法中,我有以下代码。此代码将适配器数据集中的图像加载到ImageView中。在调用ImageView将新项添加到适配器的数据集之前,代码也会等待图像加载到recursivelyLoadURLs中。

    Glide.with(context)
            //items[[position] is a string that contains a URL 
            .load(items[position])
            .listener(object : RequestListener<Drawable> {
                override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                    holder.progressBar.visibility = View.GONE
                    context.recursivelyLoadURLs()
                    return false
                }

                override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                    holder.progressBar.visibility = View.GONE
                    context.recursivelyLoadURLs()
                    return false
                }

            })
            .apply(RequestOptions()
                    .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC))
            .into(holder.imageView)

方法recursivelyLoadURLs位于父Activity类中。从本质上讲,这种方法的作用是什么

1]添加另一个URL到imageRecyclerView的适配器的数据集和

2]致电notifyDataSetChanged所以imageRecyclerView更新:

fun recursivelyLoadURLs() {


    if (currentImageURLs.size >= targetImageURLs.size) {
        return
    }

    currentImageURLs.add(targetImageURLs[currentImageURLs.size])

    //The code crashes on this line
    mainview.imageRecyclerView.adapter.notifyDataSetChanged()


}

但是,代码在上面的代码示例中标记的行上以java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling异常崩溃。

我怀疑这种情况正在发生,因为imageRecyclerView在调用notifyDataSetChanged时仍在计算布局。

如何延迟调用context.recursivelyLoadURLs直到布局完成计算?

或者,我如何在recursivelyLoadURLs中添加延迟,以便notifyDataSetChanged仅在imageRecyclerView完成计算其新布局后调用?

android kotlin android-recyclerview android-glide illegalstateexception
2个回答
1
投票

tompee建议发布一个Runnable,以保证在运行notifyDataSetChanged之前,回收站视图已经布置了它的子项。

因此,我用notifyDataSetChanged取代了

    mainview.imageRecyclerView.post({
        mainview.imageRecyclerView.adapter.notifyDataSetChanged()
    })

这解决了这个问题。


0
投票

您可以阅读RecyclerView.Adapter.notifyDataSetChanged上的文档

此事件未指定数据集的更改内容,强制任何观察者假定所有现有项和结构可能不再有效。 LayoutManagers将被迫完全重新绑定并重新布局所有可见视图。

如果您正在编写适配器,则尽可能使用更具体的更改事件会更有效。依靠notifyDataSetChanged()作为最后的手段。

这里有一些可能有用的提示*希望它有帮助:)

  1. 尽量不要使用notifyDataSetChanged(),特别是在你的onBindViewHolder中。请改用notifyItemChanged(position)。它效率更高,内存成本更低。
  2. 如果你真的需要使用notifyDataSetChanged(),请在准备好所有数据后使用它(也许在currentImageURLs.size >= targetImageURLs.size时使用它)
© www.soinside.com 2019 - 2024. All rights reserved.