Search code examples
androidmultithreadinglistviewandroid-asynctaskandroid-lazyadapter

LazyAdapter duplicates images


I have a Lazy adapter that add the title, subtitle, and picture to a ListView. Lately I have been noticing in my ListView that my images are being duplicated.

Here is where I add my array to the adapter

protected void onPostExecute(String result) {                   
    LazyAdapter adapter = new LazyAdapter(Services.this,menuItems);     
    serviceList.setAdapter(adapter);
}

Here is where I call the async method to add my image (its a url thats why it is in a async method)

vi.findViewById(R.id.thumbnail).setVisibility(View.VISIBLE);
title.setText(items.get("title")); // Set Title
listData.setText(items.get("htmlcontent")); // Set content          
thumb_image.setBackgroundResource(R.layout.serviceborder);//Adds border
new setLogoImage(thumb_image).execute(); // Async Method call

And here is where I set my bitmap image

private class setLogoImage extends AsyncTask<Object, Void, Bitmap> {
        private ImageView imv;            

        public setLogoImage(ImageView imv) {
             this.imv = imv;                 
        }

    @Override
    protected Bitmap doInBackground(Object... params) {
        Bitmap bitmap = null;
        try {               
            bitmap = BitmapFactory.decodeStream((InputStream)new URL(items.get("thumburl")).getContent());

        } catch (MalformedURLException e) {             
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bitmap;
    }
    @Override
    protected void onPostExecute(Bitmap result) {           
        imv.setImageBitmap(Bitmap.createScaledBitmap(result, 50, 50, false));
    }
}

The items variable is a HashMap that stores my info. I get the position of the data given to the adapter and assign it to the items HashMap. Like so:

items = new HashMap<String, String>();
items = data.get(position);

This happens randomly, it seems, and it gets annoying to see the wrong picture there about 30% of the time, especially when I'm trying to debug.

Any help would be great. Thanks

Here is an image to see what is happening enter image description here


Solution

  • Any time you have something that happens randomly, and you have any kind of a thread, you should think two works, Race Condition. Basically, your AsyncTasks are all loading the same image. They should be passed in the value to load. I noticed you aren't doing anything with params. I'm not sure exactly what you should do, but the problem is somewhere in your AsyncTask.

    @Override
    protected Bitmap doInBackground(Object... params) {
        Bitmap bitmap = null;
        try {               
            bitmap = BitmapFactory.decodeStream((InputStream)new URL(items.get("thumburl")).getContent());
    
        } catch (MalformedURLException e) {             
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        return bitmap;
    }
    

    You should probably pass in the URL (Or the string it represents). In this example, I pass in the URL, but feel free to change it around how you want. The key thing is, you should pass a representation of the image location into the function, rather than try to figure out what image to use when you are in the function.

    new setLogoImage(new Url(items.get("thumburl"))).execute(); // Async Method call
    
    
    @Override
    protected Bitmap doInBackground(Url... input) {
        Bitmap bitmap = null;
        try {               
            bitmap = BitmapFactory.decodeStream((InputStream)input[0]).getContent());
    
        } catch (MalformedURLException e) {             
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        return bitmap;
    }