【问题标题】:Android widget won't switch layouts more than onceAndroid 小部件不会多次切换布局
【发布时间】:2014-01-12 05:13:47
【问题描述】:

我正在向一个旧应用程序添加一个小部件,该小部件正在从我用来在后台(警报)轮询数据的服务中更新。每次服务获得结果时,我都会更新小部件。这目前工作正常。

// 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 views创建为widget_error,否则我启动服务)。

为什么widget_error 布局第一次通过onUpdate 正确显示,但当用户启用然后禁用后台更新设置时却没有?

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

【问题讨论】:

    标签: android android-widget


    【解决方案1】:

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

    看来,由于某种原因,您在 AppWidgetProvider(即在 onUpdate)中获得的 Context 实例仅在第一次时有效 - 或者,在以下情况下无效我自己发送广播。我不知道为什么。

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

    Source is available here.

    【讨论】:

      猜你喜欢
      • 2010-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多