onDelete 后的 android 小部件仍在监听

标签 android widget listener

我有一个服务在 GameLogic 单例中调用一些更新方法。 GameLogic 可能会决定需要进行某些状态更新。在这种情况下,它会通知监听器有关 StatusUpdateEvent 的信息。然后听众更新他们的 View 等。

public class GameLogic {
    // ... attributes ...
    private static GameLogic instance = null;
    private GameLogic() {
        // singleton pattern
    }
    public static synchronized GameLogic getInstance() {
        if (instance == null) {
            instance = new GameLogic();
        }
        return instance;
    }
    public void checkStatus() {
        // called by service
        // ... some checks
        notifyStatusUpdate(new StatusUpdateEvent());
    }
    public void addStatusUpdateListener(StatusUpdateListener listener) {
        if (!listeners.contains(listener)) {
            listeners.add(listener);
        }
    }
    public void removeStatusUpdateListener(StatusUpdateListener listener) {
        listeners.remove(listener);
    }
    protected synchronized void notifyStatusUpdate(StatusUpdateEvent event) {
        for (StatusUpdateListener l : listeners) {
            l.onStatusUpdate(event);
        }
    }
}

我有一个应该监听StatusUpdateEvent的小部件:

public class ProjectWidget extends AppWidgetProvider implements StatusUpdateListener {
    // ... attributes ...
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        this.context = context;
        this.appWidgetManager = appWidgetManager;
        this.remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_2x1);
        this.thisWidget = new ComponentName(context, ProjectWidget.class);

        GameLogic.getInstance().addStatusUpdateListener(this);
    }

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        Toast.makeText(context, "onDeleted", Toast.LENGTH_SHORT).show();
        GameLogic.getInstance().removeStatusUpdateListener(this);
        super.onDeleted(context, appWidgetIds);
    }
    @Override
    public void onStatusUpdate(StatusUpdateEvent e) {
        android.util.Log.d("ProjectWidget", "onStatusUpdate");
        // here some class fields are updated like this.project = e.getProject();
        // ...
        updateViews();
        appWidgetManager.updateAppWidget(thisWidget, remoteViews);
    }
    // ... updateViews() etc.
}

但是现在的问题是: 我将小部件添加到主屏幕,一切都很好。然后,如果我从主屏幕删除小部件,我会看到 onDelete Toast,但之后我仍然会看到该日志条目:ProjectWidget onStatusUpdate。

所以监听器没有被删除..为什么?我该如何做这些事情?

谢谢!

最佳答案

So the listener is not removed.. why? and how can I do that stuff?

你遇到的是内存泄漏。

AppWidgetProvider 是一个 transient 对象。它将存活足够长的时间来处理 onUpdate() 或其他应用程序小部件生命周期方法,然后它就会消失。

永远永远永远永远永远永远永远尝试让AppWidgetProvider的生命周期比这更长,例如按原样将其注册在静态上下文中。您正在泄漏内存,因为 AppWidgetProvider 不会被垃圾收集。

当您调用 removeStatusUpdateListener() 时,您拥有的 AppWidgetProvider 实例与您在 addStatusUpdateListener() 中使用的实例不同。因此,删除操作是一个无操作(您正在删除从未注册的内容),并且原始监听器将永远保留在那里。

让您的 GameLogic 或其他任何内容直接更新您的应用小部件 RemoteViews

关于onDelete 后的 android 小部件仍在监听,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4408184/

相关文章:

flutter - Flutter转换不同类型的图像类

javascript - Javascript/Jquery 监听器

android - 防止 View 在 RelativeLayout 中重叠

android - 在android平台上启动服务

android - 类型不匹配。需要 : Array<Uri>! 找到 : Array<Uri? >

css - 增加页脚小部件宽度和居中菜单(WordPress)

java - 使用 Action.SEND 从另一个应用程序接收隐式 Intent 时显示错误的 Activity

java - 将坏词保留到数据库实体中的最佳方法是什么?

java - 通过前台监听器调用后台布局监听器

JavaFX 检索 tableView 中拖动列的索引