代码之家  ›  专栏  ›  技术社区  ›  Foobar

调用notifyDataSetChanged时如何避免IllegalStateException?

  •  0
  • Foobar  · 技术社区  · 7 年前

    我有一个横向回收视图称为 imageRecyclerView ImageView ImageAdapter 图像回收视图 ArrayList 包含URL的字符串。这个 阵列列表 被称为 currentImageURLs .

    图像回收视图 一次一个。

    onBindViewHolder 类I有以下代码。此代码将适配器数据集中的图像加载到 图片框 . 代码还将等待图像加载到 打电话之前 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)
    

    方法 递归加载URL 在父活动类中。从本质上说,这种方法的作用是

    图像回收视图 的适配器的数据集和

    2] 呼叫 notifyDataSetChanged 所以 图像回收视图 更新:

    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 在上面代码示例中标记的行上。

    图像回收视图 通知数据设置 正在呼叫。

    我怎么能推迟打电话 context.recursivelyLoadURLs 直到布局完成计算?

    或者,我怎么能在里面加个延迟 递归加载URL ,所以 只调用一次 图像回收视图

    2 回复  |  直到 6 年前
        1
  •  2
  •   Foobar    7 年前

    tompee建议发布一个Runnable,以保证recycler视图在运行之前已经显示了它的子对象 notifyDataSetChanged

    因此,我取代了 通知数据设置 具有

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

    这就解决了问题。

        2
  •  0
  •   Yosi Pramajaya    7 年前

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

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

    如果您正在编写一个适配器,那么如果可以的话,使用更具体的更改事件总是会更有效。最后一个办法是使用notifyDataSetChanged()。

    以下是一些可能有用的建议,希望能有所帮助:)

    1. 尽量不要使用 notifyDataSetChanged() ,尤其是在onBindViewHolder中。使用 notifyItemChanged(position) 相反。它的效率更高,内存成本更低。
    2. 如果你真的需要 notifyDataSetChanged() ,在准备好所有数据后使用它(可能在 currentImageURLs.size >= targetImageURLs.size