I'm displaying a list of contacts (name + picture) using the ListView
. In order to make the initial load fast, I only load the names first, and defer picture loading. Now, whenever my background thread finishes loading a picture, it schedules my adapter's notifyDataSetChanged()
to be called on the UI thread. Unfortunately, when this happens the ListView
does not re-render (i.e. call getView()
for) the items that are already on-screen. Because of this, the user doesn't see the newly-loaded picture, unless they scroll away and back to the same set of items, so that the views get recycled. Some relevant bits of code:
private final Map<Long, Bitmap> avatars = new HashMap<Long, Bitmap>();
// this is called *on the UI thread* by the background thread
@Override
public void onAvatarLoaded(long contactId, Bitmap avatar) {
avatars.put(requestCode, avatar);
notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// snip...
final Bitmap avatar = avatars.get(contact.id);
if (avatar != null) {
tag.avatar.setImageBitmap(avatar);
tag.avatar.setVisibility(View.VISIBLE);
tag.defaultAvatar.setVisibility(View.GONE);
} else {
tag.avatar.setVisibility(View.GONE);
tag.defaultAvatar.setVisibility(View.VISIBLE);
if (!avatars.containsKey(contact.id)) {
avatars.put(contact.id, null);
// schedule the picture to be loaded
avatarLoader.addContact(contact.id, contact.id);
}
}
}
AFAICT, if you assume that notifyDataSetChanged()
causes the on-screen items to be re-created, my code is correct. However, it seems that is not true, or maybe I'm missing something. How can I make this work smoothly?
BaseAdapter
, and I'm already callingnotifyDataSetChanged()
manually. So that answer does not apply to me. – WashedupnotifyDataSetInvalidated()
– MixImageView
s and changing their bitmap directly, without relying ongetView
. But it seems rather messy. Especially since my actual code is slightly more complicated as I'm not changing just theImageView
, I'm changing other stuff as well (multiple data sources). I'd rather have all my item-render code ingetView
. – WashedupNotifies the attached observers that the underlying data is no longer valid or available. Once invoked this adapter is no longer valid and should not report further data set changes.
-- I'd like to keep using my adapter. – WashedupinvalidateViews()
on theListView
afternotifyDataSetChanged()
, but it seems the JavaDoc is confusing, as it still doesn't actually redraw the already on-screen items. – Washedup