0

I'm using the Universal Image Loader library to load images in my listview, it loads the images but I notice that if you scroll quickly the first time you can see the wrong images being loaded first before the correct image.

How can I stop this effect. Here is my entire class below.

public MyListAdapter(Context context, List<VenueDetails> m_venue_details) {
    super(context, R.layout.venue_list_row, m_venue_details);

    this.context = context;
    this.venue_details = new ArrayList<VenueDetails>();
    this.venue_details = m_venue_details;
    df = new DecimalFormat("#.##");
}

@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
@Override
public View getView(int position, View v, ViewGroup parent) {

    final ViewHolder holder;
    final VenueDetails vD =  venue_details.get(position);   

    if (inflater == null) {
        inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    if (v == null) {
        v = inflater.inflate(R.layout.venue_list_row, parent,false);
        holder = new ViewHolder();
        holder.venue_name = (TextView) v.findViewById(R.id.venue_name);
        holder.venue_dist = (TextView) v.findViewById(R.id.venue_dist);
        holder.curr_loc = (TextView) v.findViewById(R.id.curr_loc);
        holder.ll = (FrameLayout) v.findViewById(R.id.venue_frame);
        holder.pett_btn = (Button) v.findViewById(R.id.venue_pett);
        holder.img = (ImageView) v.findViewById(R.id.venue_logo);

        v.setTag(holder);

    }else{
        holder = (ViewHolder) v.getTag();
    }

    holder.img.setTag(vD.logo);

    if(vD.list_img == null){
        myAppObj.getImageLoader().loadImage(holder.img.getTag().toString(), new ImageLoadingListener() {

            @Override
            public void onLoadingStarted(String imageUri, View view) {
                holder.img.setBackgroundResource(R.drawable.placeholder_venue);
            }

            @Override
            public void onLoadingFailed(String imageUri, View view,
                    FailReason failReason) {    
                holder.img.setBackgroundResource(R.drawable.placeholder_pin);                   
            }

            @Override
            public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                holder.img.setBackgroundDrawable(new BitmapDrawable(loadedImage));
                if(vD.list_img == null){
                    vD.list_img = new BitmapDrawable(loadedImage);
                }
            }

            @Override
            public void onLoadingCancelled(String imageUri, View view) {
                holder.img.setBackgroundResource(R.drawable.placeholder_venue);
            }
        });
    }else{
        holder.img.setBackgroundDrawable(vD.list_img);
    }

    if(vD != null){         

        holder.venue_name.setText(vD.venueName.toUpperCase());
        venue_details.get(position).venue_distance = Double.parseDouble(df.format(Utils.distance(myAppObj.getMyLatitude(), myAppObj.getMyLongitude(), vD.latitude, vD.longitude, 'K') * 0.000621371192));
        holder.venue_dist.setText(df.format(vD.venue_distance)+" Miles");


        holder.venue_curr_loc.setText(my_address.toUpperCase());

        if (vD.petted == 1) {

            holder.pett_btn.setVisibility(View.VISIBLE);
            holder.ll.setVisibility(View.VISIBLE);

            holder.pett_btn.setOnClickListener(new OnClickListener() {
                @Override               
                public void onClick(View v) {                   
                    if(dialog_Callback!=null)
                        dialog_Callback.onDialogCalled(0, vD.id);
                }
            });

        } else {

            holder.pett_btn.setVisibility(View.GONE);
            holder.ll.setVisibility(View.GONE);
        }           
    }

    return v;
}

@Override
public boolean isEnabled(int position) {
    if (venue_details.get(position).petted == 1) {
        return false;
    } else {
        return true;
    }
}

static class ViewHolder{
    TextView venue_name;
    TextView venue_dist;
    TextView venue_curr_loc;
    FrameLayout ll;
    Button pett_btn;
    ImageView img;
}
user2611073
  • 77
  • 2
  • 9

3 Answers3

2

Its because its recycling views, so that second argument (View v) in getView already holds the content from a previous list item. So you need to clear that imageView as it won't change immediately (due to the image being downloaded).

Changing your code to something like this should work

if (v == null) { 

...

}else{
    holder = (ViewHolder) v.getTag();
    holder.img.setImageResource(0);
    holder.img.setBackgroundDrawable(0);
}
kassim
  • 3,880
  • 3
  • 26
  • 27
1

I faced this problem before and i realized that: First: 1- The class that the AsyncTask that present in your Universal Image Loader library should have a WeakReference for the imageView that the image will be load in.

2- while scrolling and displaying a row with an image its AsyncTask is still getting the image, you have to be sure that there is no other AsyncTask will be start for the same image.

after a long searching journey to fix your exact problem i found another class you can customize it to fit your requirements.

package com.nweave.utils;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyStore;

import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;

import com.nweave.view.ProductArrayAdapter;

public class ImageDownloader {
    private ProductArrayAdapter productArrayAdapter;

    public ImageDownloader(ProductArrayAdapter productArrayAdapter) {
        this.productArrayAdapter = productArrayAdapter;
    }

    public void download(String name, String url, ImageView imageView,
            ProgressBar progressBar) {
        if (cancelPotentialDownload(url, imageView)) {
            BitmapDownloaderTask bitmapDownloaderTask = new BitmapDownloaderTask(
                    name, imageView, progressBar);
            DownloadedDrawable downloadedDrawable = new DownloadedDrawable(
                    bitmapDownloaderTask);
            imageView.setImageDrawable(downloadedDrawable);
            bitmapDownloaderTask.execute(url);
        }
    }

    private class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
        String url;
        private final WeakReference<ImageView> imageViewReference;
        private final String productName;
        private final ProgressBar progressbar;

        public BitmapDownloaderTask(String name, ImageView imageView,
                ProgressBar progressBar) {
            imageViewReference = new WeakReference<ImageView>(imageView);
            productName = name;
            progressbar = progressBar;
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            HttpResponse response = null;
            HttpClient httpsClient = getHttpsClient();
            HttpGet httpGet = new HttpGet();
            try {
                httpGet.setURI(new URI(params[0]));

                response = httpsClient.execute(httpGet);
                Bitmap currentBitMap = BitmapFactory.decodeStream(response
                        .getEntity().getContent());
                productArrayAdapter.cacheImages.saveImages(productName,
                        currentBitMap);
                return currentBitMap;
            } catch (URISyntaxException e) {
                Log.e(ImageDownloader.class.getSimpleName() + ":doInBackground",
                        e.getMessage());
            } catch (ClientProtocolException e) {
                Log.e(ImageDownloader.class.getSimpleName() + ":doInBackground",
                        e.getMessage());
            } catch (IOException e) {
                Log.e(ImageDownloader.class.getSimpleName() + ":doInBackground",
                        e.getMessage());
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            if (isCancelled()) {
                result = null;
            }
            if (imageViewReference != null) {
                ImageView imageView = imageViewReference.get();
                BitmapDownloaderTask bitmapDownloaderTask = ImageDownloader
                        .getBitmapDownloaderTask(imageView);
                if (this == bitmapDownloaderTask) {
                    imageView.setImageBitmap(result);
                    imageView.setVisibility(View.VISIBLE);
                    progressbar.setVisibility(View.INVISIBLE);
                }
            }
        }
    }

    private static class DownloadedDrawable extends ColorDrawable {
        private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

        public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
            bitmapDownloaderTaskReference = new WeakReference<BitmapDownloaderTask>(
                    bitmapDownloaderTask);
        }

        public BitmapDownloaderTask getBitmapDownloaderTask() {
            return bitmapDownloaderTaskReference.get();
        }
    }

    private static boolean cancelPotentialDownload(String url,
            ImageView imageView) {
        BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
        if (bitmapDownloaderTask != null) {
            String bitmapUrl = bitmapDownloaderTask.url;
            if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
                bitmapDownloaderTask.cancel(true);
            } else {
                return false;
            }
        }
        return true;
    }

    private static BitmapDownloaderTask getBitmapDownloaderTask(
            ImageView imageView) {
        if (imageView != null) {
            Drawable drawable = imageView.getDrawable();
            if (drawable instanceof DownloadedDrawable) {
                DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
                return downloadedDrawable.getBitmapDownloaderTask();
            }
        }
        return null;
    }

    private static HttpClient getHttpsClient() {
        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore
                    .getDefaultType());
            trustStore.load(null, null);
            SSLSocketFactory sslSocketFactory = new MySSLSocketFactory(
                    trustStore);
            sslSocketFactory
                    .setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            HttpParams params = new BasicHttpParams();
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
            SchemeRegistry registry = new SchemeRegistry();
            registry.register(new Scheme("http", PlainSocketFactory
                    .getSocketFactory(), 80));
            registry.register(new Scheme("https", sslSocketFactory, 443));
            ClientConnectionManager ccm = new ThreadSafeClientConnManager(
                    params, registry);
            return new DefaultHttpClient(ccm, params);
        } catch (Exception e) {
            Log.e(ImageDownloader.class.getSimpleName() + ":getHttpsClient",
                    e.getMessage());
            return new DefaultHttpClient();
        }
    }
}
Omar HossamEldin
  • 3,033
  • 1
  • 25
  • 51
1

The best solution would be to use Picasso very easy to use and much better performace

Amanni
  • 1,924
  • 6
  • 31
  • 51