виджет андроида после onDelete еще слушает - PullRequest
2 голосов
/ 10 декабря 2010

У меня есть служба, которая вызывает некоторые методы обновления в GameLogic -инглтоне. GameLogic может решить, что необходимо обновить статус. В этом случае он сообщает своим слушателям о StatusUpdateEvent. Затем слушатели обновляют свое мнение и т. Д.

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, но после этого я все еще вижу эту запись журнала: ProjectWidget onStatusUpdate.

Так что слушатель не удаляется .. почему? и как я могу сделать это?

Спасибо!

1 Ответ

3 голосов
/ 10 декабря 2010

Так что слушатель не удаляется .. почему? и как я могу это делать?

То, что у вас есть, это утечка памяти.

AppWidgetProvider является временным объектом. Он будет жить достаточно долго, чтобы обработать onUpdate() или другой метод жизненного цикла виджета приложения, а затем исчезнет.

Никогда никогда никогда никогда никогда никогда пытайтесь прожить AppWidgetProvider дольше этого, например, регистрируя его в статическом контексте, когда вы являются. Вы теряете память, так как AppWidgetProvider не будет собирать мусор.

Когда вы звоните removeStatusUpdateListener(), у вас есть экземпляр AppWidgetProvider, отличный от того, который вы использовали с addStatusUpdateListener(). Следовательно, операция удаления запрещена (вы удаляете что-то, что никогда не регистрировалось), и оригинальный слушатель останется там навсегда.

Пусть ваш GameLogic или любой другой обновит виджет вашего приложения RemoteViews напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...