ListView shows wrong and duplicates images

喜欢而已 提交于 2020-01-03 16:37:18

问题


I have a ListView and 12 ImageViews in it.

Every ImageView has different image which is loading from url. Images are shuffled and sometimes duplicated either I scroll or not.

I tried 10 other ways to solve this problem but have not succeeded.

This is the code I download and show images:

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);
    }

}

Thanks in advance for any ideas!


回答1:


Before:

imageDownloader.downloadImage(dataList.get(position).getPhotoPath(), true, downloadInterface);

Put:

viewHolder.photo.setImageBitmap(null);

This will reset the ImageView's bitmap, as it is being recycled and therefore keeping its image.




回答2:


You should have something like this:

if (!viewHolder.isDownloading) {
    // download the image in a worker thread
} else {
    // cancel the current downloading and start a new one with the new url
}

Since ListView items are reusable. Your items are starting the image downloads, but when you start scrolling, those same items could still be downloading the images when they are already being reused. So when the worker thread has finished, the bitmaps are set in the wrong place and even worse, you never started the downloads for those reused items because the viewholder.isDownloading said it was already downloading an image.




回答3:


A) You only initiate the download when the convertView is instantiated. You are recycling the rows so you may have a data set larger than the number of row Views that you actually use. This is not the right place to begin downloading an image. You want to do this per viewed position, not per View instantiated.

B) When you fire off a background task to download the image it may return later (after fetching) and replace a row with the wrong image as the row may now represent the wrong position (given row recycling).

Asynchronous image loading in a recycling ListView is slightly more complicated than it first seems. As the user scrolls through the list, you'll need to fire off downloads when a position is viewed, and cancel calls that are now redundant (as they are for a previously visible position).

You may wish to read more on view recycling in a ListView to get a better understanding of what is happening.

Also consider using an image downloading/caching library that handles these complexities such as Picasso.




回答4:


Use UniversalImageLoader library to load images.. Try this

ImageLoader.getInstance().displayImage(url, holder.imgView, options);

to load images inside adapter..

Use DisplayImageOptions as follows inside constructor of adapter

  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();

and add

  StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

inside onCreateView/onCreate of fragment/activity contaning the list



来源:https://stackoverflow.com/questions/23432372/listview-shows-wrong-and-duplicates-images

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!