在数据更改后,停止在回收器视图适配器中将图像加载到 ImageView 中的所有线程的最佳方法



嗨,我有我的适配器用于回收器视图,我需要显示一个大列表(带有图像的不同列表)。我从单独的线程加载到 ImageView 中的所有图像。每个 ImageView 的每个线程。问题在于,当我更改适配器的数据并调用 notifyDataSetChanged();- 有时新的图像视图显示来自先前数据集的图像。我知道发生这种情况是因为RecyclerView正在重用ViewHolder项目 - 其中旧线程仍在下载旧图像,而不是新图像。所以我想知道当我的适配器中的数据集发生变化时如何停止所有线程。可能是将所有线程放入数组中并在调用 notifyDataSetChanged();但我认为还有更优雅的解决方案吗?这是我的代码:

@Override
public void onBindViewHolder(ItemHolder holder, int position) {
            ........
            holder.itemIcon.setImageResource(tree.getDefaultCover());
            BitmapWorkerTask bitmapWorkerTask = new BitmapWorkerTask(holder.itemIcon, tree);
            bitmapWorkerTask.execute(file);
            ......
}

然后在我的工作线程任务中,我在postExecute方法中设置位图

    @Override
    protected void onPostExecute(Bitmap result) {
        super.onPostExecute(result);
         mIconView.setImageBitmap(result);
    }

AsycTask.execute一次只能执行一个任务/线程。 下一个在上一个完成时开始。 在您的任务中,您必须至少在doInBackground年初和onPostExecute年初检查isCanceled()

如果持有者知道

taks并且任务知道持有者,你可以要求每个持有者停止它的任务(调用cancle方法)。

由于持有者和任务之间有循环引用,因此存在内存泄漏的风险。

您必须让 Shure 让持有人在任务被关闭/完成或配置更改(即屏幕旋转)时忘记它的任务。

我已经在APhotoManager中完成了此操作。它包含一个带有网格视图的GalleryCursorFragment和一个带有嵌入式GridCellViewHolder的GalleryCursorFragment

Android Dev 网站解决了在列表 UI 中处理图像的确切问题。基本上,这个想法是在可绘制对象上定义一个包装器,该包装器保留对应该为其加载图像的任务的引用。由于视图是在列表 UI 中回收的,因此甚至在执行为其加载图像的任务之前,就可能回收特定视图。此模式有助于抢占并取消任务。

https://developer.android.com/training/displaying-bitmaps/process-bitmap.html#concurrency

这里不需要重新发明轮子。只需使用滑行。

Glide.with(this).load("img_url").into(imageView);

做。

您可以在 asyncktack 中停止执行以在回收器视图中获取新图像使用此代码停止 asncktack 如果 (asyncktask != null){ asyncktask .cancel(true);}然后调用 notifyDataSetChanged();

最新更新