在启动器重新启动时,小部件未更新。

4
我有一个小部件,它会在配置更改时(例如屏幕方向)和手机解锁时自动更新。这个过程涉及为我的小部件上的按钮设置onClick处理程序。这很有效,但我发现有一种用法导致我的应用程序不响应onClick事件。这种情况是当启动器重新启动时。
是否有一种方法可以检测到启动器何时重新启动,以便我可以手动更新我的小部件?或者是否有另一种方法来确保onClick处理程序不会丢失?

2个回答

10

原来我在写代码时频繁调用new RemoteViews(),实际上只需要调用一次生成视图,然后在需要时引用该实例即可。我的解决方案是,定义一个类变量来存储这个单一的RemoteView实例,并提供一个getter方法来访问它。


1
即使您提出的修复措施,问题似乎仍然存在。我认为这与此处的Issue 28216相同。 - Anirudh Ramanathan
这个描述还比较模糊。能否请您提供更多的细节呢?"Called it once" 是什么意思呢?对于每个更新迭代,您是创建一个 RemoteViews 实例,还是只创建一次并保留引用(例如在服务中)? - Sean Aitken
这个工作得非常好,谢谢!当然,像往常一样,Android文档是垃圾。我在各个地方寻找正确的答案,这是唯一有效的答案。@CleverCoder 是的,只保留你创建的单个实例一次。因此,在Widget的onUpdate中,仅在引用为空时才创建remoteViews对象! - Radu
请注意,使用这种方法解决“启动器重新启动”问题确实存在问题。我测试了一个带有列表视图的主页小部件。随着时间的推移,当触发更多的appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, list_id)时,整个主页小部件会变得非常缓慢。我的猜测是,“单例”远程视图将继续执行其不断增长的累积指令。 - Cheok Yan Cheng

0

@Glitch提出的方案在某些情况下可能不适用,特别是对于带有ListView的应用程序小部件。这是因为ListView会变得非常缓慢(尝试滚动ListView),在多次调用appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, list_id)之后。

我猜测,单个RemoteView实例将在列表中保留其所有执行指令。随着时间的推移,指令列表将增长。每次调用appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, list_id)时,都会重新执行大型指令列表。

我的解决方案如下。但是,我相信它只能在某些设备上运行,因为并非所有设备在启动器重新启动期间都会收到相同的广播消息。

@SuppressLint("NewApi")
@Override
public void onReceive(Context context, Intent intent) {
    final String action = intent.getAction();

    if (action.equals("com.sec.android.widgetapp.APPWIDGET_RESIZE")) {
        // https://dev59.com/h3PYa4cB1Zd3GeqPo-5v
        handleTouchWiz(context, intent);

        // Possible launcher restart.
        handleLauncherRestart(context, intent);
    } else if (action.equals("android.appwidget.action.APPWIDGET_UPDATE_OPTIONS")) {

        // Possible launcher restart.            
        handleLauncherRestart(context, intent);
    } 

    super.onReceive(context, intent);
}

private void handleLauncherRestart(Context context, Intent intent) {
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID);
    updateAppWidget(context, appWidgetManager, appWidgetId);
}

private void handleTouchWiz(Context context, Intent intent) {
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

    int appWidgetId = intent.getIntExtra("widgetId", 0);
    int widgetSpanX = intent.getIntExtra("widgetspanx", 0);
    int widgetSpanY = intent.getIntExtra("widgetspany", 0);

    if (appWidgetId > 0 && widgetSpanX > 0 && widgetSpanY > 0) {
        Bundle newOptions = new Bundle();
        // We have to convert these numbers for future use
        // https://dev59.com/G2kw5IYBdhLWcg3wQ4hd
        if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, widgetSpanY * 74 - 2);
            newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, widgetSpanX * 74 - 2);

        } else {
            newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, widgetSpanY * 70 - 30);
            newOptions.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, widgetSpanX * 70 - 30);
        }

        onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
    }
}

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