【问题标题】:Widget not updated on launcher restart启动器重新启动时小部件未更新
【发布时间】:2011-10-02 19:03:48
【问题描述】:

我有一个小部件,只要有配置更改(例如屏幕方向)以及手机解锁,它就会自行更新。这个过程涉及为我的小部件上的按钮设置onClick 处理程序。这很好用,但是我发现有一个用例导致我的应用程序不响应onClick 事件。这种特殊情况是每当启动器自行重新启动时。

有没有办法检测启动器何时重新启动,以便我可以手动更新我的小部件?还是有其他方法可以确保onClick 处理程序不会丢失?

【问题讨论】:

标签: android widget launcher android-pendingintent


【解决方案1】:

原来我是在向new RemoteViews() 发送垃圾邮件,而我应该只调用一次以生成视图,然后在需要时引用该实例。在我的解决方案中,我有一个存储这个 RemoteView 实例的类变量和一个访问它的 getter。

【讨论】:

  • 即使在您建议的修复之后问题似乎仍然存在。我觉得这里和Issue 28216是一样的。
  • 这很模糊。你能提供更多细节吗? “叫它一次”..这是什么意思?对于每次更新迭代,您创建一个 RemoteViews 实例,或者您创建一次并保留引用(例如,在服务中)。
  • 效果很好,谢谢! Ofc,像往常一样,Android 文档是废话。我在各个地方寻找正确答案,这是唯一有效的答案。 @CleverCoder 是的,只保留一次创建的单个实例。所以,在 Widget 的 onUpdate 中,只有当你的引用为 null 时才创建 remoteViews 对象!
  • 请注意,使用这种方法解决“启动器重启”确实会出现问题。我使用带有列表视图的主页小部件进行了测试。随着时间的推移,当更多的appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, list_id) 被触发时,整个home 小部件会变得很慢。我的疯狂猜测是,“单例”远程视图将继续执行其不断增长的累积指令。
【解决方案2】:

@Glitch 的建议可能不适用于某些情况,尤其是带有ListView 的应用小部件。这是因为在多次调用 appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, list_id) 之后,ListView 会变得非常慢(尝试滚动 ListView)。

我的猜测是,单个 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")) {
        // http://stackoverflow.com/questions/17396045/how-to-catch-widget-size-changes-on-devices-where-onappwidgetoptionschanged-not
        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
        // http://stackoverflow.com/questions/10008521/appwidget-size-calculation
        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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 2020-01-21
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多