Android小部件不会多次切换布局

时间:2013-12-23 23:32:57

标签: android android-widget

我正在将一个小部件添加到一个旧应用程序中,我正在使用的服务进行更新,以便在后台轮询数据(在警报上)。每次服务获得结果时我都会更新小部件。这目前正常。

// Called from inside my service when it has results
private void updateWidget(List<Earthquake> earthquakes) {
    AppWidgetManager manager = AppWidgetManager.getInstance(this);
    int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(this, WhatsShakingWidgetProvider.class));
    if (appWidgetIds == null || appWidgetIds.length == 0)
        return;

    Earthquake earthquake = earthquakes.get(0);
    RemoteViews views = new RemoteViews(getPackageName(), R.layout.widget_detail);

    // Update views
    views.setTextViewText(R.id.widget_detail_latest_magnitude, earthquake.getFormattedMagnitude());
            // etc...

    // Update each widget
    for(int appWidgetId : appWidgetIds) {
        manager.updateAppWidget(appWidgetId, views);
    }
}

此投票服务是可选的;它可以在应用程序的设置中打开或关闭。

如果在用户添加小部件时服务已关闭,则会按预期显示widget_error布局。用户可以点击小部件以输入设置并打开后台更新。当他们这样做时(打开或关闭设置),我播放ACTION_APPWIDGET_UPDATE。小部件正确输入onUpdate,并在下次运行时由服务正确更新(我已将其设置为小部件触发onUpdate中的服务调用 - 见下文)。

当服务在启用后被禁用时,小部件会正确显示widget_error布局 - 即使所有已禁用的案例代码都已运行,它也会保留原有布局

这是用户切换设置时调用的代码(Source):

// If our user has widgets, we should update those - let the widget do the updating depending on the prefs, though.
Intent intent = new Intent(this, WhatsShakingWidgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
// Use an array and EXTRA_APPWIDGET_IDS instead of AppWidgetManager.EXTRA_APPWIDGET_ID,
// since it seems the onUpdate() is only fired on that:
int[] ids = { R.xml.widget_info };
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
sendBroadcast(intent);

这是onUpdate中应该更新小部件的代码,但不是:

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
        int[] appWidgetIds) {
    super.onUpdate(context, appWidgetManager, appWidgetIds);
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    boolean backgroundUpdatesEnabled = prefs.getBoolean(PreferenceActivity.KEY_PREF_ALLOW_BG_NOTIFICATIONS,
            DefaultPrefs.BG_NOTIFICATIONS_ENABLED);
    if (!backgroundUpdatesEnabled) {
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_error);

        // Update click to take to preferences
        Intent intent = new Intent(context, PreferenceActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        views.setOnClickPendingIntent(R.id.widget_error_parent_container, pendingIntent);

        // Update each widget
        appWidgetManager.updateAppWidget(appWidgetIds, views);
    } else {
        // Let's get some data for the user! Service does the work of updating the views.
        WakefulIntentService.sendWakefulWork(context, GeonetService.class);
    }
}

Logcat中没有记录错误。单步执行此操作,我会在预期时正确输入if的每个部分(也就是说,如果用户关闭了设置,那么我创建RemoteViews viewswidget_error,否则我启动服务)。

为什么widget_error布局首次显示onUpdate时是否正确,但是当用户启用后禁用后台更新设置时却不能正确显示?

我已尝试将其包装在RelativeLayout并设置错误消息/内容的可见性,但显示相同的行为 - 我无法在最初隐藏后显示错误消息它

1 个答案:

答案 0 :(得分:1)

我最终在两个地方复制代码(首选项活动和小部件提供程序)并且它工作正常。唯一的变量似乎是Context对象。

出现由于某种原因,您在Context(即AppWidgetProvider)中获得的onUpdate个实例仅在第一次运行时 - 或者,我自己发送广播时不起作用。我不确定为什么。

我将重复的代码提取到一个单独的类中,然后传入我可用的Context实例,无论是ServiceActivity还是{{1} }(这是AppWidgetProvider)。这正确地更新了小部件,我可以从任何有BroadcastReceiver的地方调用它。

Source is available here