开发者

Lazy-loading images in ListView on Android

开发者 https://www.devze.com 2023-01-16 22:31 出处:网络
I implemented the lazy-loading images in my ListView. I use a AsyncTask to download the image from the internet and bind it to the ImageView in the UIThread.

I implemented the lazy-loading images in my ListView. I use a AsyncTask to download the image from the internet and bind it to the ImageView in the UIThread.

It's working except that when I scroll the ListView vary fast, the downloaded images sometimes are binded into the wrong items in the list.

I guess the problem is from the reuse of convertView in the BaseAdapter. Any ideas to solve it?

Many thanks.

EDIT: I post the answer as following:

public void setBitmap(int position, Bitmap image) {
    View itemView = mListView.getChildAt(position - mListView.getFirstVisiblePosition());
    if (itemView != null) {
        ImageView itemImageView = (ImageView) itemVi开发者_JAVA技巧ew.findViewById(R.id.item_imageview);
        itemImageView.setImageBitmap(image);
    }
}


There are two problems that will arise during lazy loading of images in a ListView.

  1. The old images are still shown until the new ones are loaded. This is easy just set the ImageView to an image is loading view or set it to invisible before starting the image download.
  2. The second problem is harder to solve. Imagine you are scrolling very fast through your list. Now your views may be recycled before the old AsyncTask has finished loading the image. You now have two tasks running that in the onPostExecute method will set an image to the imageview. Now for a short time the wrong image will be shown until the second Task finishes, or even worse for some network related reason they don't finish in the order they started and you have the wrong image overwrite the correct image. To solve this you have to check what image should be displayed after the task finished. In the View class are two methods for things exact like this one:

    setTag and getTag You can bind any object to the imageview that comes into your mind. In most of the cases I use setTag to bind the URL of the image as a String to the imageview before I start a task. Now I can cast getTag to a String after the task finished and compare the URL that should be displayed with the URL that I downloaded and only set the image if necessary.


Create a function called void setBitmap(Bitmap bitmap, int position) or similar in your adapter. Let your AsyncTask call this method when a new bitmap is available. This method may then call notifyDataSetChanged() on the UI-Thread itself to ensure the views get refreshed. Holding references to views in an adapter (even by holding them in an AsyncTask) is dangerous!

0

精彩评论

暂无评论...
验证码 换一张
取 消