Yeah! I think I know this problem. Right now, your getView method sets your ImageView as follows:
- Returns the movie object in position
- Displays the thumbnail URL of the movie
- Using this url, it tries to find the image in cache
- If he finds an image, he sets it
- If he cannot find the image, he runs an async network request to retrieve it, and installs it after downloading it.
Your issus arises because ListView reuses' View s strings. When the first View scrolls from the screen, and does not inflate a new one, the ListView passes the current off-screen View row as a convertView for reuse (this is for efficiency).
When your getView gets a convertView that is reused, its ImageView has already been installed from the row that had it before, so you see the old image from the off-screen View row. Using the current getView process getView you check for the presence of a new row image and do not find it in the cache, it starts a request to download it. While you are loading, you see the old image until you get a new image.
To fix this, you need to make sure that you immediately set each field in the View line to make sure you don't have a View displaying obsolete data. I suggest you install ImageView on the drawable resource by default (you set it in your R.layout.movie_data_row ) while you wait for the network to load to receive the image.
@Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = vi.inflate(R.layout.movie_data_row, null); } ParkCinema movie = movieDataItems.get(position); ImageView imageView = (ImageView) convertView.findViewById(R.id.movie_thumb_icon); if (movie != null) { String url = movie.poster(); if (url != null) { Bitmap bitmap = fetchBitmapFromCache(url); if (bitmap == null) {
-Edit -
Updated to be even more robust using drawable . You also have a problem with your BitmapDownloaderTask , it does not handle / null errors. Try adding this as well.
@Override protected void onPostExecute(Bitmap bitmap) { addBitmapToCache(url, bitmap); if (bitmap == null) {
source share