开发者

android widget after onDelete still listening

开发者 https://www.devze.com 2023-01-30 02:36 出处:网络
I have a Service that calls some update-methods in a GameLogic-singleton. TheGameLogic may decide that some status-update is needed. In this case it informs its listeners about a StatusUpdateEvent. Th

I have a Service that calls some update-methods in a GameLogic-singleton. TheGameLogic may decide that some status-update is needed. In this case it informs its listeners about a StatusUpdateEvent. The listeneres then update their view etc.

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);
        }
    }
}

I have a widget that should listen to the 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);
    }

    @Overri开发者_如何学编程de
    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.
}

But the problem now is: I add the widget to the homescreen, everythings fine. Then if I delete the widget from the homescreen, I see the onDelete Toast, but afterwards I still see that Log entry: ProjectWidget onStatusUpdate.

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

Thanks!


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

What you have is a memory leak.

The AppWidgetProvider is a transient object. It will live long enough to process an onUpdate() or other app widget lifecycle method, and then it goes away.

Never never never never never never try to have an AppWidgetProvider live longer than this, such as by registering it in a static context as you are. You are leaking memory, as the AppWidgetProvider will not get garbage-collected.

When you are calling removeStatusUpdateListener(), you have a different AppWidgetProvider instance than you used with addStatusUpdateListener(). Hence, the remove operation is a no-op (you are removing something never registered), and the original listener will remain there forever.

Have your GameLogic or whatever update your app widget RemoteViews directly.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号