我在这些方面看到了很多问题,而且我一遍又一遍地看到同样的答案。我不想为我的应用程序所拥有的每种小部件都提供服务,特别是因为我的应用程序已经拥有2个持久性服务。
具体来说,如果我的一个现有服务发现数据已更改,我想更新我的小部件。在计时器上执行此操作很烦人,因为它可能是更新之间的天数,也可能在一小时内有几天。我希望我的小部件始终显示最新信息。
Android小部件设计似乎是基于您的小部件在需要时提取信息的基础上工作,我认为有很多明智的场景,活动可能希望将数据推送到小部件。
阅读下面的答案,了解我如何确切地解决这个问题。据我所知,如果做得好,没有任何不利影响。
答案 0 :(得分:37)
要强制更新特定窗口小部件提供程序的窗口小部件,我们需要执行以下操作:
第1步 - 设置我们的AppWidgetProvider
我不会详细介绍如何创建info xml文件或更改Android Manifest - 如果你不知道如何正确创建一个小部件,那么你应该先阅读很多教程。< / p>
以下是一个示例AppWidgetProvider
类:
public class MyWidgetProvider extends AppWidgetProvider {
public static final String WIDGET_IDS_KEY ="mywidgetproviderwidgetids";
public static final String WIDGET_DATA_KEY ="mywidgetproviderwidgetdata";
}
@Override
public void onReceive(Context context, Intent intent) {
if (intent.hasExtra(WIDGET_IDS_KEY)) {
int[] ids = intent.getExtras().getIntArray(WIDGET_IDS_KEY);
if (intent.hasExtra(WIDGET_DATA_KEY)) {
Object data = intent.getExtras().getParcelable(WIDGET_DATA_KEY);
this.update(context, AppWidgetManager.getInstance(context), ids, data);
} else {
this.onUpdate(context, AppWidgetManager.getInstance(context), ids);
}
} else super.onReceive(context, intent);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
update(context, appWidgetManager, appWidgetIds, null);
}
//This is where we do the actual updating
public void update(Context context, AppWidgetmanager manager, int[] ids, Object data) {
//data will contain some predetermined data, but it may be null
for (int widgetId : ids) {
.
.
//Update Widget here
.
.
manager.updateAppWidget(widgetId, remoteViews);
}
}
第2步 - 发送广播
在这里,我们可以创建一个静态方法,让我们的小部件更新。重要的是我们使用自己的键和小部件更新操作,如果我们使用AppWidgetmanager.EXTRA_WIDGET_IDS,我们不仅会破坏我们自己的小部件,还会破坏其他小部件。
public static void updateMyWidgets(Context context, Parcelable data) {
AppWidgetManager man = AppWidgetManager.getInstance(context);
int[] ids = man.getAppWidgetIds(
new ComponentName(context,MyWidgetProvider.class));
Intent updateIntent = new Intent();
updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
updateIntent.putExtra(MyWidgetProvider.WIDGET_ID_KEY, ids);
updateIntent.putExtra(MyWidgetProvider.WIDGET_DATA_KEY, data);
context.sendBroadcast(updateIntent);
}
如果对多个提供商使用此方法,请确保使用不同的密钥。否则你可能会发现widget a的代码更新小部件b,这可能会产生一些奇怪的后果。
第3步 - 点击
进行更新另一件好事是让我们的小部件在点击时进行恶意更新。将以下代码添加到update方法中以实现此目的:
RemoteViews views =
new RemoteViews(context.getPackageName(),R.layout.mywidget_layout);
Intent updateIntent = new Intent();
updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
updateIntent.putExtra(myWidgetProvider.WIDGET_IDS_KEY, ids);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, 0, updateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.view_container, pendingIntent);
此代码将导致在单击窗口小部件时调用onUpdate方法。
备注强>
答案 1 :(得分:4)
很抱歉OP有一个迟到的答案,但对于其他任何人,你可以使用这样的方法来更新特定类型的所有app小部件(布局和类):
public static void updateAllWidgets(final Context context,
final int layoutResourceId,
final Class< ? extends AppWidgetProvider> appWidgetClass)
{
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), layoutResourceId);
AppWidgetManager manager = AppWidgetManager.getInstance(context);
final int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, appWidgetClass));
for (int i = 0; i < appWidgetIds.length; ++i)
{
manager.updateAppWidget(appWidgetIds[i], remoteViews);
}
}
这样做会为您的布局创建一个RemoteViews
然后获取AppWidgetManager
并查找您提供的类的所有应用小部件,迭代它们并更新它们。
答案 2 :(得分:-3)
每当你处理类型时,只需简单地处理静态就可以了。并且,如果您希望基于“触发器”发生特定事情,我总是建议基于事件的编程... Intent本质上是Android中的默认“事件”(用于在事件中传递数据,确保对象实现Parcelable接口)。
在各种论坛和SDK文档中有很多这些概念的例子。