开发者

How to update an ImageView in a custom ListView using ASyncTask?

I know there's already tons of similar questions, but I checked over twenty answers and none of them solves my problem.

First, I have an adapter extending SimpleCursorAdapter. I use custom view in it, including an ImageView. The layout is:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="@dimen/listitem_height" android:gravity="center_vertical">
<ImageView android:id="@+id/row_image" android:layout_width="@dimen/listitem_height"
    android:layout_height="fill_parent" android:paddingRight="@dimen/spaceLarge"
    android:layout_centerVertical="true" android:layout_marginLeft="@dimen/spaceMedium"
    android:src="@drawable/unknown_album" />
<LinearLayout android:layout_width="fill_parent"
    android:layout_height="fill_parent" android:orientation="vertical"
    android:gravity="center_vertical|left">
    <TextView android:id="@+id/row_text" android:layout_width="fill_parent"
        androi开发者_运维百科d:textAppearance="?android:attr/textAppearanceMedium"
        android:gravity="center_vertical|left" android:layout_height="wrap_content" />
    <TextView android:id="@+id/title" android:layout_width="fill_parent"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:gravity="center_vertical|left" android:layout_height="wrap_content"
        android:textColor="#95D0B4" />
</LinearLayout>

Then, the ImageView needs some time to load image, so if I do it in main thread, the scrolling will become horrible. Thus I want to use an AsyncTask to load images, but now I face the problem of ListView, which reuses views when scrolling.

That is, code below does not work:

class ImageSetter extends AsyncTask<String, Void, Bitmap> {

    private ImageView iv;

    ImageSetter(ImageView iv) {
        this.iv = iv;
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        String path = (String) params[0];
        try {
            return BitmapFactory.decodeFile(path);
        } catch (OutOfMemoryError e) {
            Log.w(Utils.TAG, "", e);
            return null;
        }
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        iv.setImageBitmap(result);
        super.onPostExecute(result);
    }

}

which I call execute() in bindView() in the adapter. The ImageView changes while scrolling, and the result Bitmap is set into wrong position.

Does anyone how to resolve this problem? Thank you very much!

P.S. I also meet serious OutOfMemory problem when scrolling the list fast. I quite have no idea about how to avoid the bitmap memory leak problem, since I can't recycle them as long as they are in the list.


Adapter reuses Views inside ListView. As a result you are never sure if

private ImageView iv;

contains ImageView object you wanted to set. You should use id for finding proper cell in the list.

Reconsider using thumbnails or decrease size of images. You can read more here: Lazy load of images in ListView

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜