2015-03-25 2 views
3

Я исправляю устаревшее приложение, у которого есть проблема с сохранением объектов списком наблюдателей в классе, реализующем Observable. Правильное удаление наблюдателей было бы большой задачей, поэтому я решил использовать WeakReference, чтобы преодолеть это. Проблема в том, что вызов Observable.addObserver(new WeakReference(something)) невозможен, так как WeakReference не реализует Observer. Так я думал о создании класса называется WeakObserver так:Могу ли я передать WeakReference наблюдаемым слушателям?

public class WeakObserver<T> extends WeakReference<T> implements Observer { 
private T observer; 

public WeakObserver(final T observer){ 
    super(observer); 
    this.observer = observer; 
} 

@Override 
public void update(Observable o, Object arg) { 
    ((Observer)observer).update(o, arg); 
} 
} 

Проблема здесь вполне очевидна - помимо не безопасных отлиты в update методе, я создаю еще одну ссылку на объект, который я хочу, чтобы получить мусор ,

Является ли что-то вроде этого даже возможным, или я пытаюсь сделать что-то глупое?

+0

Итак, объекты 'Observer', которые вы хотите разрешить быть GC'd, и проблема в том, что они зарегистрированы в списке« Наблюдаемые »? –

+0

Да, точно. Единственное, о чем я могу думать, это переопределить методы «Observable» для использования 'WeakReference ' объектов – NeplatnyUdaj

+0

Нужен ли WeakObserver наблюдателю переменных экземпляра? Почему бы не полагаться на метод get() метода WeakReference в методе обновления - проверить, является ли null, а если не делегировать вызов ненулевой ссылке? – copeg

ответ

1

Вы, вероятно, может сделать эту работу, но вы хотите, чтобы ваши слабые наблюдаемые в имеют слабые ссылки на реальные Observable с, не до be слабых ссылок.

Кроме того, этого недостаточно, чтобы реальные наблюдатели могли быть GC'd; вам также необходимо отменить объекты оболочки из Observable, как только это произойдет. Такого рода вещи, что ссылки на очереди, но если вы не хотите, чтобы изменить Observable класс, то вы можете сократить так:

public class WeakObserver implements Observer { 
    private final WeakReference<Observer> observer; 
    private final Observable observed; 

    public WeakObserver(Observer observer, Observable observed){ 
     this.observer = new WeakReference<Observer>(observer); 
     this.observed = observed; 
    } 

    @Override 
    public void update(Observable o, Object arg) { 
     Observer realObserver = observer.get(); 

     if (realObserver != null) { 
      realObserver.update(o, arg); 
     } else { 
      observed.deleteObserver(this); 
     } 
    } 
} 

Это WeakObserver специфичен к одному Observable, как это необходимо автоматически удалите его, когда базовый реальный Observer является GC'd. Вы могли бы избежать этого, используя ReferenceQueue, если хотите и можете соответствующим образом изменить Observable.

+0

Это, вероятно, решение, которое я ищу. Я все еще не могу заставить GC очистить наблюдателей, но они, вероятно, упоминаются где-то в другом месте, поэтому мне приходится копаться в куче кучи. – NeplatnyUdaj

2

(Чтобы скомпоновать мой комментарий) Вместо того, чтобы придерживаться ссылки, вы можете положиться на метод get WeakReference. Класс также может быть parametized поэтому приведение не является необходимым в способе обновления:

private class ObserverWeak extends WeakReference<Observer> implements Observer{ 

    public ObserverWeak(Observer referent) { 
     super(referent); 
    } 

    @Override 
    public void update(Observable obs, Object arg) { 
     if (super.get() != null){ 
      super.get().update(obs, arg); 
     } 
    } 


} 
Смежные вопросы