Duplicate items in GridView widget
Asked Answered
G

4

6

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;
    }
}
Galacto answered 22/3, 2012 at 7:33 Comment(2)
put the source class that called getViewAt()Astrogeology
@Astrogeology - the framework is calling getViewAtGalacto
C
3

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.

Caeoma answered 17/4, 2012 at 21:20 Comment(1)
I hoped for this, but no.. everything is match_parent or specific size, no wrap_content.Galacto
N
1

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();
}
Nebulose answered 3/7, 2012 at 19:59 Comment(0)
H
1

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.

Hepcat answered 9/6, 2013 at 7:8 Comment(0)
G
0
@Override public long getItemId(int pos) { return pos; }

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

Not sure if this has something to do with the problem, but the example has return true for hasStableIds()

Goldfinch answered 29/3, 2012 at 16:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.