Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
    }
}
like image 251
Ran Avatar asked Mar 22 '12 07:03

Ran


3 Answers

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.

like image 128
scott1055 Avatar answered Nov 04 '22 07:11

scott1055


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();
}
like image 37
orip Avatar answered Nov 04 '22 08:11

orip


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.

like image 1
sophocan Avatar answered Nov 04 '22 09:11

sophocan