Doug, you were right.
If I inflate a new view each time instead of using the cached
convertView, the images never show incorrectly. This is obviously less
efficient, but it's right. I need to look more closely to see if I was
abusing the ViewHolder pattern, but I don't see how I was.
This is what I'm doing now in convertView():
public View getView(int position, View convertView, ViewGroup
parent)
{
if (position >= appList.size()) {
return null;
}
convertView = mInflater.inflate
(R.layout.app_list_item, null);
ObjectToShow objectToShow = appList.get
(position);
ObjectToShow objectToShowWithMetadata =
appMap.get
(objectToShow.getKey());
if(objectToShow != null) {
if(objectToShowWithMetadata.getName() !
= null) {
((TextView)
convertView.findViewById(R.id.app_list_item_name)).setText
(objectToShowWithMetadata.getName());
}
if(iconMap.get(objectToShow.getKey()) !
= null) {
((ImageView)
convertView.findViewByI(R.id.app_list_item_icon)).setImageBitmap
(iconMap.get(objectToShow.getKey()));
}
} else {
((TextView)convertView.findViewById
(R.id.app_list_item_name)).setText(defaultText);
((ImageView)convertView.findViewByI
(R.id.app_list_item_icon)).setImageDrawable(defaultIcon);
}
return convertView;
}
Any thoughts?
On Jun 27, 4:17 pm, Doug <[email protected]> wrote:
> Have you tried *not* caching the component views in your ViewHolder
> object - instead looking them up whenever you get a redraw request?
> You may find that the list is re-using objects, and your image issue
> is simply an artifact of that.
>
> Doug
>
> On Jun 26, 10:56 pm, Peter <[email protected]> wrote:
>
>
>
> > > There's not adefaultnumberof views created for an adapter. A list
> > > creates as many views as it needs to fill the screen. Views get reused
> > > only when you start scrolling or when the adapter send a
> > > notifyDatasetChanged(). You say you have a thread updating the data,
> > > what is exactly that thread doing? Please show code.
>
> > Here is some code. Perhaps it will help.
>
> > ********** the worker thread ***************
> > --------------------------------------
>
> > class IconLoaderThread extends Thread {
> > List<ObjectToShow> appList;
> > void loadAllResources(List<ObjectToShow> appList) {
> > this.appList = appList;
> > start();
> > }
>
> > public void run() {
> > int maxSize;
>
> > for (int i = 0; i < maxSize; i++) {
> > ObjectToShow appInfo = appList.get(i);
> > // network access occurs here
> > Bitmap icon =
> > appQuery.lookupAppIcon(appInfo);
> > Message msg =
> > handler.obtainMessage(MSG_REFRESH_APP_ICON);
> > Bundle data = new Bundle();
> > data.putString("s3ObjectKey",
> > appInfo.getS3ObjectKey());
> > msg.obj = icon;
> > msg.setData(data);
> > handler.sendMessage(msg);
> > }
> > Message doneMsg =
> > handler.obtainMessage(MSG_ICONS_DONE);
> > handler.sendMessage(doneMsg);
> > }
> > }
>
> > ********** the handler ***************
> > --------------------------------------
>
> > private Handler handler = new Handler() {
> > public void handleMessage(Message msg) {
> > ObjectToShow appInfo;
> > switch (msg.what) {
> > case MSG_INIT_APP_LIST:
> > initProgressBar();
> >
> > handler.sendEmptyMessage(MSG_NEXT_LOAD_STEP);
> > break;
> > case MSG_REFRESH_APP_ICON:
> > Bitmap icon = (Bitmap)msg.obj;
> > String s3ObjectKey =
> > msg.getData().getString("s3ObjectKey");
> > if(icon == null || s3ObjectKey == null) {
> > Log.w(TAG, "Error loading icon");
> > } else {
> >
> > efficientAdapter.updateAppInfoIcon(s3ObjectKey, icon);
> > }
> > break;
> > case MSG_REFRESH_APP_METADATA:
> > appInfo = (ObjectToShow)msg.obj;
> > if(appInfo == null) {
> > Log.w(TAG, "Error loading icon");
> > } else {
> >
> > efficientAdapter.updateAppInfoMetadata(appInfo);
> > }
> > break;
> > case MSG_METADATA_DONE:
> > metadataLoaded = true;
> >
> > handler.sendEmptyMessage(MSG_NEXT_LOAD_STEP);
> > break;
> > case MSG_ICONS_DONE:
> > iconsLoaded = true;
> >
> > handler.sendEmptyMessage(MSG_NEXT_LOAD_STEP);
> > break;
> > case MSG_NEXT_LOAD_STEP:
> > if (metadataLoaded && iconsLoaded) {
> > doneLoadingMetadata();
> > }
> > else if (metadataLoaded || iconsLoaded) {
> > if (firstRun) {
> > // Set the adapter here.
> > firstRun = false;
> >
> > appListView.setAdapter(efficientAdapter);
> > dismissLoadingMessage();
> > }
> > initIconThread();
> > }
> > else {
> > initMetadataThread();
> > }
> > break;
> > default:
> > break;
> > }
> > }
> > };
>
> > ********** the adapter ***************
> > --------------------------------------
>
> > class EfficientAdapter extends BaseAdapter {
> > private List<ObjectToShow> appLocalList;
> > // IndexedObjectToShow just adds the int positions
> > associated with
> > the item in the ListView
> > private Map<String, IndexedObjectToShow> appLocalMap;
> > private Map<String, Bitmap> iconMap =
> > Collections.synchronizedMap
> > (new HashMap<String, Bitmap>());
> > AppInfoComparator appInfoComparator = new
> > AppInfoComparator();
>
> > public void initList(List<ObjectToShow> appList) {
> > if (appList != null) {
> > appLocalList =
> > Collections.synchronizedList(appList);
>
> > Collections.sort(appLocalList,
> > appInfoComparator);
>
> > appLocalMap = new TreeMap<String,
> > IndexedObjectToShow>();
> > Iterator<ObjectToShow> iter =
> > appLocalList.iterator();
> > int i = 0;
> > while (iter.hasNext()) {
> > ObjectToShow thisInfo = iter.next();
> >
> > appLocalMap.put(thisInfo.getS3ObjectKey(), new IndexedObjectToShow
> > (i, thisInfo));
> > i++;
> > }
> > appLocalMap =
> > Collections.synchronizedMap(appLocalMap);
> > }
> > }
>
> > public long getItemId(int position) {
> > int maxSize = appLocalList.size();
> > if( (position < 0) || (position >= maxSize)) {
> > Log.w(TAG, "Position out of bounds in List
> > Adapter");
> > return -1;
> > }
> > return
> > appLocalMap.get(appLocalList.get(position).getS3ObjectKey
> > ()).index;
> > }
>
> > public EfficientAdapter(Context c, List<ObjectToShow>
> > appList) {
> > if (appList != null) {
> > // Just refresh the list
> > appLocalList = appList;
>
> > Collections.sort(appLocalList,
> > appInfoComparator);
>
> > appLocalMap = new TreeMap<String,
> > IndexedObjectToShow>();
> > Iterator<ObjectToShow> iter =
> > appLocalList.iterator();
> > int i = 0;
> > while (iter.hasNext()) {
> > ObjectToShow thisInfo = iter.next();
> >
> > appLocalMap.put(thisInfo.getS3ObjectKey(), new IndexedObjectToShow
> > (i, thisInfo));
> > i++;
> > }
> > }
> > }
>
> > public int getCount() {
> > return appLocalList.size();...
>
> read more »
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---