Your code in your getView implementation of the adapter looks good at
first sight. The structure of this method looks good.
I think there are a few issues though.
In your getView(...) method, you access the variable 'appList':
if (position >= appList.size()) {
return null;
}
and
ObjectToShow objectToShow = appList.get
(position);
ObjectToShow objectToShowWithMetadata =
appMap.get
The only place i can find a declared variable called 'appList' in your
example code is the one that is a private member of IconLoaderThread:
class IconLoaderThread extends Thread {
List<ObjectToShow> appList;
...
}
In short, this 'appList' is accessed in two threads without any
synchronization or attempt to make it immutable.
Also, the plain assignment here worries me:
public EfficientAdapter(Context c, List<ObjectToShow>
appList) {
if (appList != null) {
// Just refresh the list
--> appLocalList = appList; <---
...
}
...
}
because in the method 'initList' you do something similar, but you
assign a copy of appList to appLocalList.
On Jun 30, 12:43 am, Peter <[email protected]> wrote:
> 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();
> > > - Hide quoted text -
>
> - Show quoted text -...
>
> 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
-~----------~----~----~----~------~----~------~--~---