How to create an app widget with a configuration activity, and update it for the first time?

前端 未结 4 738
自闭症患者
自闭症患者 2020-12-12 22:42

This is driving me crazy. I don\'t know how to update the app widget from the configuration activity, even with the recommended practises. Why the update method is not calle

4条回答
  •  难免孤独
    2020-12-12 23:16

    You are correct that the onUpdate-method isn't triggered after the configuration activity finishes. It is up to your configuration activity to do the initial update. So you need to build the initial view.

    This is the gist of what one should do at the end of the configuration:

    // First set result OK with appropriate widgetId
    Intent resultValue = new Intent();
    resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    setResult(RESULT_OK, resultValue);
    
    // Build/Update widget
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
    
    // This is equivalent to your ChecksWidgetProvider.updateAppWidget()    
    appWidgetManager.updateAppWidget(appWidgetId,
                                     ChecksWidgetProvider.buildRemoteViews(getApplicationContext(),
                                                                           appWidgetId));
    
    // Updates the collection view, not necessary the first time
    appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.notes_list);
    
    // Destroy activity
    finish();
    

    You already set the result correctly. And you call ChecksWidgetProvider.updateAppWidget(), however updateAppWidget() does not return the correct result.

    updateAppWidget() at current returns an empty RemoteViews-object. Which explains why your widget is completely empty at first. You haven't filled the view with anything. I suggest that you move your code from onUpdate to a static buildRemoteViews() method which you can call from both onUpdate and updateAppWidget():

    public static RemoteViews buildRemoteViews(final Context context, final int appWidgetId) {
            final RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.checks_widget);
            rv.setRemoteAdapter(android.R.id.list, intent);
    
            // The empty view is displayed when the collection has no items. It should be a sibling
            // of the collection view.
            rv.setEmptyView(android.R.id.list, android.R.id.empty);
    
            // Here we setup the a pending intent template. Individuals items of a collection
            // cannot setup their own pending intents, instead, the collection as a whole can
            // setup a pending intent template, and the individual items can set a fillInIntent
            // to create unique before on an item to item basis.
            final Intent toastIntent = new Intent(context, ChecksWidgetProvider.class);
            toastIntent.setAction(ChecksWidgetProvider.TOAST_ACTION);
            toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
            toastIntent.setData(Uri.parse(toastIntent.toUri(Intent.URI_INTENT_SCHEME)));
            final PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            rv.setPendingIntentTemplate(android.R.id.list, toastPendingIntent);
    
            return rv;
    }
    
    public static void updateAppWidget(final Context context, final AppWidgetManager appWidgetManager, final int appWidgetId) {
        final RemoteViews views = buildRemoteViews(context, appWidgetId);
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }
    
    @Override
    public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    
        // Perform this loop procedure for each App Widget that belongs to this provider
        for (int appWidgetId: appWidgetIds) {
            RemoteViews rv = buildRemoteViews(context, appWidgetId);
            appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
        }
    }
    

    That should take care of the widget initialization.

    The last step before calling finish() in my sample code is updating the collection view. As the comment says, this isn't necessary the first time. However, I include it just in case you intend to allow a widget to be re-configured after it has been added. In that case, one must update the collection view manually to make sure the appropriate views and data get loaded.

提交回复
热议问题