Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onGetViewFactory only called once for multiple widgets

I have an appwidget which uses ListView. I have created a class that extends RemoteViewsService:

public class AppWidgetService extends RemoteViewsService {
    @Override
    public RemoteViewsFactory onGetViewFactory(Intent intent) {
        return (new AppWidgetListFactory(this.getApplicationContext(), intent));
    }
}

In my AppWidgetProvider, I call the following method for each instance of the widget (for each appWidgetId):

private static void fillInList(RemoteViews widget, Context context, int appWidgetId) {
    Intent intent = new Intent(context, AppWidgetService.class);
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    widget.setRemoteAdapter(R.id.appwidget_listview, intent);
}

The constructor of the AppWidgetListFactory

public AppWidgetListFactory(Context context, Intent intent) {
    this.context = context;
    appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);

    System.out.println("New TVAPWLF for: " + appWidgetId);
    trains = WidgetData.getInstance().widgetMap.get(appWidgetId);
}

Now the problem is, that the fillInList method gets called just as often as there are instances of the widget, but the onGetViewFactory method only gets called once. This results in all the widgets showing the same data.

How can I fix this?

like image 711
nhaarman Avatar asked Jul 05 '12 18:07

nhaarman


2 Answers

I haven't tested this myself, but looking at the source code for RemoteViewsService.onBind(), I believe you can not just vary the extras in your Intent in order for it to detect that a new call to your onGetViewFactory() method is needed since it uses the Intent.filterEquals() method for the comparison:

Determine if two intents are the same for the purposes of intent resolution (filtering). That is, if their action, data, type, class, and categories are the same. This does not compare any extra data included in the intents.

I would suggest passing the information that you need (widget id?) through the Intent's data instead, maybe something like:

private static void fillInList(RemoteViews widget, Context context, int appWidgetId) {
    Intent intent = new Intent(context, AppWidgetService.class);
    intent.setData(Uri.fromParts("content", String.valueOf(appWidgetId), null));
    widget.setRemoteAdapter(R.id.appwidget_listview, intent);
}

and respectively on the receiving side:

public TreinVerkeerAppWidgetListFactory(Context context, Intent intent) {
    this.context = context;
    appWidgetId = Integer.valueOf(intent.getData().getSchemeSpecificPart());

    System.out.println("New TVAPWLF for: " + appWidgetId);
    trains = WidgetData.getInstance().widgetMap.get(appWidgetId);
}
like image 91
Joe Avatar answered Sep 27 '22 22:09

Joe


Based on the above description another trick you can do if you are setting intent extra other than string could be:

Random random = new Random();
intent.setType(String.valueOf(random.nextInt(1000)));

This will invoke a call to onGetViewFactory();

like image 37
amit srivastava Avatar answered Sep 28 '22 22:09

amit srivastava