ListView 显示错误并重复图像
Posted
技术标签:
【中文标题】ListView 显示错误并重复图像【英文标题】:ListView shows wrong and duplicates images 【发布时间】:2014-06-19 09:18:25 【问题描述】:我有一个 ListView 和 12 个 ImageView。
每个 ImageView 都有从 url 加载的不同图像。图像被打乱,有时我滚动或不滚动都会重复。
我尝试了 10 种其他方法来解决这个问题,但都没有成功。
这是我下载并显示图像的代码:
private static class ViewHolder
ImageView imageViewPhoto;
Bitmap photo;
boolean isDownloading;
@Override
public View getView(final int position, View convertView, ViewGroup parent)
final ViewHolder viewHolder;
if (convertView == null)
// ...classical view holder and other operations...
if (!viewHolder.isDownloading)
viewHolder.isDownloading = true;
IImageDownload downloadInterface = new IImageDownload()
@Override
public void onError(VolleyError error, String url)
@Override
public void onDownloaded(Bitmap response, String url)
viewHolder.photo = response;
notifyDataSetChanged();
;
imageDownloader.downloadImage(dataList.get(position).getPhotoPath(), true, downloadInterface);
convertView.setTag(viewHolder);
else
viewHolder = (ViewHolder) convertView.getTag();
if (viewHolder.photo != null)
viewHolder.imageViewPhoto.setImageBitmap(viewHolder.photo);
else
viewHolder.imageViewPhoto.setImageResource(R.drawable.gray_background);
提前感谢您的任何想法!
【问题讨论】:
不是您问题的答案,但您应该考虑使用 Picasso 之类的东西将图像异步加载到图像视图中。您可以将您发布的所有代码更改为一行。 【参考方案1】:之前:
imageDownloader.downloadImage(dataList.get(position).getPhotoPath(), true, downloadInterface);
放:
viewHolder.photo.setImageBitmap(null);
这将重置 ImageView 的位图,因为它正在被回收并因此保留其图像。
【讨论】:
这个想法很合适! 执行 setImageBitmap(null) 将是万无一失的,尤其是当图像加载器加载图像时,它至少需要几秒钟。在下载过程中,listview / recyclerview 可能已经为另一个项目回收了 viewholder。【参考方案2】:你应该有这样的东西:
if (!viewHolder.isDownloading)
// download the image in a worker thread
else
// cancel the current downloading and start a new one with the new url
因为 ListView 项目是 reusable。您的项目正在开始图像下载,但当您开始滚动时,这些相同的项目可能仍在下载已被重复使用的图像。因此,当工作线程完成时,位图设置在错误的位置,更糟糕的是,您从未开始下载那些重复使用的项目,因为 viewholder.isDownloading 表示它已经在下载图像。
【讨论】:
是不好的做法,如果您的互联网速度较慢,您将得到一个空图像:) 和更多错误:D【参考方案3】:A) 只有在 convertView
被实例化时才开始下载。您正在回收这些行,因此您的数据集可能大于您实际使用的行数View
s。这不是开始下载图像的正确位置。您希望按查看的位置执行此操作,而不是按 View
实例化。
B) 当您启动后台任务以下载图像时,它可能会稍后返回(在获取之后)并用错误的图像替换一行,因为该行现在可能代表错误的位置(给定行回收)。
回收ListView
中的异步图像加载比最初看起来要复杂一些。当用户在列表中滚动时,您需要在查看位置时触发下载,并取消现在多余的调用(因为它们是针对以前可见的位置)。
您可能希望在ListView
中阅读更多关于视图回收的信息,以更好地了解正在发生的事情。
还可以考虑使用处理这些复杂性的图像下载/缓存库,例如Picasso。
【讨论】:
【参考方案4】:使用UniversalImageLoader 库加载图像.. 试试这个
ImageLoader.getInstance().displayImage(url, holder.imgView, options);
在适配器内加载图像..
在适配器的构造函数中如下使用DisplayImageOptions
options = new DisplayImageOptions.Builder()
.showImageOnLoading(android.R.color.transparent)
.showImageForEmptyUri(android.R.color.transparent)
.showImageOnFail(android.R.color.transparent)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
并添加
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
包含列表的片段/活动的 onCreateView/onCreate 内部
【讨论】:
以上是关于ListView 显示错误并重复图像的主要内容,如果未能解决你的问题,请参考以下文章