I am using a SimpleCursorTreeAdapter to display data in database. I am using loaders to manage all the cursors. Everything works fine. But there are some images in each of the child views. This causes a noticeable stutter when scrolling. So I want to use an asynctask to decode the images in background. Something like (pseudocode):
@Override
protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) {
super.bindChildView(view, context, cursor, isLastChild);
String imgFile = cursor.getString(MyDatabaseHelper.FILE_INDEX);
new asyncLoadImage().execute(imgFile);
}
private class asyncLoadImage extends AsyncTask<String, Void, Bitmap> {
@Override
protected Bitmap doInBackground(String... arg0) {
String imgFile = arg0[0];
return Utils.getBitMap(imgFile);//psuedocode
}
@Override
protected void onPostExecute(Bitmap bm) {
ImageView imageView = new ImageView(mCtx);
imageView.setTag(mID);
imageView.setImageBitmap(bm);
//ok got the imageview. where do I append it ??
}
}
By the time the imageview is ready in onPostExecute() function, the view provided in bindChildView might have been recycled and pointing to some different child element. How do I determine where to append the imageview?
First, don't append. You need the ImageView
there anyway. Have the ImageView
use a placeholder image, that you replace with the final image when it is ready.
Second, consider using an existing library that knows about Adapter
recycling, such as Picasso. Admittedly, I don't know if Picasso has support for ExpandableListAdapter
, as I rarely use ExpandableListView
.
If you determine that there is no suitable library, you'll need some logic in your getChildView()
and/or getGroupView()
methods that can deal with recycling and your background work. One fairly simple approach is to tuck the URL of the image needed by the ImageView
in the tag of the ImageView
via setTag()
. Your onPostExecute()
can then compare the URL it just downloaded with the URL from the ImageView
tag, and if they do not match, do not update the ImageView
. This means that you will download some images unnecessarily, so a more sophisticated approach will arrange to cancel the AsyncTask
that is downloading the image. And I am sure that there are other approaches as well.