只需更新小部件RemoteViews而不是完全创建一个新的?

5

在我的AppWidgetProvider类的onUpdate方法中,我最终执行了大量代码以便完全重新创建一个新的RemoteView对象。实际上,每次更新时我只需要在RemoteViews中设置一个TextView中的文本。

有没有办法只修改特定小部件正在使用的RemoteViews?

3个回答

20

首先,RemoteView 不是一个视图。它是一组指令,用于构建视图层次结构。它被用于在另一个进程中重新创建视图 (小部件不在您应用的进程中执行)。因此,它是可序列化和可变的。

因此,当您初始化 RemoteView 时,只需将其引用存储在某个地方,例如在自定义 AppWidgetProvider 的字段中。 下次需要它时,从字段获取并更改其中的内容。要更改 TextView 中的字符串,请使用 setString(..)

remoteView.setString(textViewId, "setText", "some text for TextView")

1
可以这样做。RemoteViews完全与应用程序/活动上下文分离,不会泄漏内存。 - Peter Knego
2
我很想这样做,但静态变量假定您只有一个小部件,对吗?如果有多个小部件,每个小部件都有自己的RemoteViews实例,那么这将无法工作。我很想将RemoteViews保存为可包含在AppWidgetOptions中的Parcelable,该选项是针对每个小部件ID设置的。 - thom_nic
@Mike 绝对是的,当实例消失时,此答案中建议使用的 RemoteViews 引用也会随之消失... - Jose_GD
@thom_nic 你可以使用一个静态的HashMap,将appWidgetId映射到RemoteViews。 - Amir Uval
@PeterKnego 是的,如果您将图像设置到远程视图中,它会泄漏内存,特别是因为每次运行时指令不会被清除;这将导致在每次小部件运行时运行所有累积的指令。 - htafoya
显示剩余3条评论

17

如果您正在使用当前的API,请注意这是2013年的更新。在您的WidgetProvider类中,有一个将执行更新的方法:

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
rv = new RemoteViews(context.getPackageName(), R.layout.widgetlayout); 
rv.setTextViewText(R.id.ofTextViewInWidgetLayoutXML, "Hello World");
appWidgetManager.partiallyUpdateAppWidget(appWidgetIds[i], rv);

请注意,现在使用的是 remoteView.setTextViewText,而不是 remoteView.setString。


1
这里的关键部分是partiallyUpdateAppWidget - Tom

0

您可以更新远程视图,然后调用

ComponentName componentName= new ComponentName(context, YourClass.class);
AppWidgetManager.getInstance(context).updateAppWidget(componentName, remoteViews);

根据我所知,这应该更新小部件


1
这并没有真正解决我的问题,因为我仍然需要创建你命名为“remoteViews”的变量。 - Kurtis Nusbaum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接