Evan Charlton wrote:
> I will be surprised if this hasn't been asked before, but I've been
> Googling for days now and haven't found anything very helpful. My
> problem is this:
> 
> I'm trying to lazy-load images into a ListView--almost exactly how
> Market does it, if you're familiar with that. It's not exactly like
> Market because the images there comes in batches whereas mine are one
> at a time, but I digress...
> 
> I have the following adapter: http://paste2.org/p/318634
> This adapter lazy-loads pages and each row's corresponding image (if
> applicable) and caches it to disk for faster loading next time. This
> all works perfectly *except* when loading images over the network,
> they come in on the wrong rows and are sometimes duplicated. I assume
> that this has to do with the adapter reusing views, but I haven't been
> able to stamp it out.

I suspect you are on the money with your assessment of the problem.

You pass in an ImageView to the AsyncTask and tell the task to replace
the image in that ImageView. However:

-- Since it is asynchronous, for a bit, the ImageView will remain
unchanged, which in the case of a recycled row will be whatever it was
before

-- If you scroll enough before the image is done loading, and the row is
recycled first, you'll get weird results (image will keep flipping to
different pictures as its various tasks complete)

I just went through implementing something very similar. I'll eventually
tease it out into something reusable and open source. Compared to the
snippet of your implementation, here are two things I did differently:

1. Rather than tie the AsyncTask to a specific ImageView, I have the
AsyncTask notify the ListView when an image load is complete, providing
it the URL of the loaded image. The ListView, when it inflates/recycles
rows, attaches the URL of the image that is supposed to be shown to each
ImageView via the setTag() method. Then, when the AsyncTask says
such-and-so URL is ready, the ListView walks the ImageViews and sees if
any are showing that image, by comparing the passed-in URL to each
ImageView's getTag(). If there's a match, ListView then loads the image
out of the AsyncTask-managed cache into the ImageView. This way, I don't
keep a strict tie between the AsyncTasks and the ImageViews. I suspect
there's a better-performing solution than my current implementation, but
it's at least tolerable for the moment.

2. Rather than try to hack around the existing AsyncTask's limitations,
I copied its source code (thank you, Android and Apache 2!) and made it
use an unbounded LinkedBlockingQueue and use more than one thread to
process it. That beats the heck out of trying to keep your own queue to
feed into the AsyncTask class's static queue.

-- 
Mark Murphy (a Commons Guy)
http://commonsware.com | http://twitter.com/commonsguy

Android 1.5 Programming Books: http://commonsware.com/books.html

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers-unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to