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
精彩评论