Duplicate items in GridView widget

UPDATE: I opened an issue, please star it if you are experiencing the same problem. http://code.google.com/p/android/issues/detail?id=28016

I have an appwidget with a gridview on it.

When I start adding items to my widget, almost always I get the first items shown twice (instead of showing the first item and second item).

If I do a widget update intent then the problem is fixed and never returns (assuming I already have two items on my gridview).

But it always happens when the first two items are added.

Any ideas what it could be?

UPDATE: I've just noticed that it always happens when a new item is added to the GridView. If I refresh the widget without adding a new item, then it works fine.

Another thing I saw is that the getViewAt method is always called twice for the first item (position zero). Maybe it's related?

I followed the sample here quite closely: http://developer.android.com/resources/samples/WeatherListWidget/src/com/example/android/weatherlistwidget/WeatherWidgetService.html

Here is my RemoteViewsService, I think this is the relevant part but I'm not sure actually. What else can affect it?

package com.manor.TestApp;

public class TestAppRemoteViewsService extends RemoteViewsService {

@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new TestAppViewsFactory(this.getApplicationContext(), intent); }

}

class TestAppViewsFactory implements RemoteViewsService.RemoteViewsFactory {

private Context mContext;

//private int mAppWidgetId;

private TestDb mDb = null;

private int mCount = 0;

private String[] mData;

public TestAppViewsFactory(Context context, Intent intent) { mContext = context;

  /*mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
          AppWidgetManager.INVALID_APPWIDGET_ID);*/

}

@Override public void onCreate() {

  mDb = new TestDb(mContext);

  mDb.open(false);

}

@Override public void onDestroy() {

  if (mDb != null)

      mDb.close();

}

@Override public int getCount() {

  Log.d("TestApp", "getCount: " + Integer.toString(mCount));

  return mCount;

}

@Override public RemoteViews getViewAt(int position) {

  Log.d("TestApp", "pos: " + Integer.toString(position));
  if (position >= mData.length)
      return null;

  Log.d("TestApp", "p: " + mData[position]);

  /*if (position > 0) {
      Log.d("TestApp", "here");
  }*/


  SharedPreferences sharedPreferences = 
      >mContext.getSharedPreferences(TestAppPreferenceActivity.SHARED_PREFS_NAME, 0);

  RemoteViews rv = new RemoteViews(mContext.getPackageName(), >R.layout.widget_item);

  // --- set text and image to remoteviews --- 

  return rv;

}

@Override public RemoteViews getLoadingView() { return null; }

@Override public void onDataSetChanged() { SharedPreferences sharedPreferences =

mContext.getSharedPreferences(TestAppPreferenceActivity.SHARED_PREFS_NAME, 0);

  String[] strs = mDb.getData();

  if (strs == null) {
      mCount = 0;
      return;
  }

  // -- fills mData from mDb --

  mCount = mData.length;

}

@Override public int getViewTypeCount() { return 1; }

@Override public long getItemId(int pos) { return pos; }

@Override public boolean hasStableIds() { return false; }

}


Is the height or widget of your GridView or any of its parent containers set to wrap_content?

After many days of trial and error, I think I fixed a similar issue with a ListView by changing its height from wrap_content to match_parent . I haven't been able to reproduce the problem after the change (so far).

I found a video explaining why wrap_content is bad for ListView's: http://www.youtube.com/watch?v=wDBM6wVEO70&t=40m45s. Maybe its similar for GridViews as well.


Similar to @Niko's comment, I had this problem until I changed the IDs to be unique per item.

For a backing array of strings, hashing them strongly to longs, or keeping (long id, String data) pairs instead may help.

Here's example code for hashing. I'm using Google Guava's Hashing , but the concept is general.

@Override
public long getItemId(int position) {
    return Hashing.sha1().hashString(mData[position]).asLong();
}

After several trials and a month search on google, today I found the solution. When using imageviews in listview, you should initiate every imageview at each getViewAt call. I've conditioned imageview selection in each case, but forgot initialization. At getViewAt I assigned a transparent image with no content. Problem solved.

链接地址: http://www.djcxy.com/p/50596.html

上一篇: Android适配器(回收视图)与assyncTask图像下载

下一篇: GridView小部件中的重复项目