android appwidget listview not updating

2019-03-20 02:38发布

问题:

I've written an AppWidget that displays some data in a ListView from a ContentProvider, but I have trouble having it update. When I first create the widget it gets populated correctly, but after the AlarmManager's PendingIntent arrives, no updates occurs on the ListView. Here's the code:

Intent update = new Intent(context, MenuWidgetProvider.class);
update.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
update.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pIUpdate = PendingIntent.getBroadcast(context, 0, update, 0);
((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).
set(AlarmManager.RTC, nextTime.toMillis(false), pIUpdate);

Log.d(TAG, "updating: " + dmt.mealName);

for (int i = 0; i < appWidgetIds.length; ++i) {
    int widgetId = appWidgetIds[i];

    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_menu);
    // meal name
    views.setTextViewText(R.id.widget_locname, prefs.getString(PREF_WIDGET_LOCNAME, ""));

    // adapter
    Intent adapter = new Intent(context, MenuWidgetAdapterService.class);
    adapter.putExtra(EXTRA_LOCATIONID, prefs.getInt(PREF_WIDGET_LOCID, -1));
    adapter.putExtra(EXTRA_MEALNAME, dmt.mealName);
    adapter.putExtra(EXTRA_DATE, dmt.date.toString());
    views.setRemoteAdapter(R.id.widget_list, adapter);

    // update
    manager.updateAppWidget(widgetId, views);
}

super.onUpdate(context, manager, appWidgetIds);

Weird thing is, when the update happens, the onUpdate() method runs--I see the output from the Log.d call--but there is no call to onDataSetChanged() in my RemoteViewsFactory. Even when I call notifyAppWidgetViewDataChanged, no effect.

回答1:

This is because your RemoteViewsFactory caches the factory it creates for each widget ID. Hence when the same widget sends a request to create a new factory (through your Widget Adapter Service), the same factory is returned. Hence, the list view is not "updated".

How I worked around it:

In your WidgetProviderClass

adapter.setData(Uri.fromParts("content", String.valueOf(appWidgetIds[i]+randomNumber), null));

where randomNumber is a random number (a public Static member of your WidgetProvider class).

Then in your RemoteViewsFactory class, do:

appWidgetId = Integer.valueOf(intent.getData().getSchemeSpecificPart())
            - WidgetProvider.randomNumber;

This "fools" the Service into thinking that it has to create a Factory for another widget, and therefore, creates a new factory with the updated values, which is attached to your widget.

Hope this helps.



回答2:

Even I had same problem. RemoteView of widget has this problem.

Solution: Send broadcast to yourself and refresh list again. i.e Set data to your complete view and then send broadcast to yopurself.

Hope this helps



回答3:

Try dynamic number

In your WidgetProviderClass:

int randomNumber=(int)(Math.random()*1000); 
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId+randomNumber);

           intent.setData(Uri.fromParts("content", String.valueOf(appWidgetId), null));

           intent.putExtra("random",randomNumber );
           intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
           rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);

And in your RemoteViewsFactory class, do :

AppWidgetId = Integer.valueOf(intent.getData().getSchemeSpecificPart());