2013-09-29 1 views
2

Предполагая следующее:Использование WeakReferenced слушателя

public interface Listener { 
    public void onListen(); 
} 

public class ActionClass { 

    WeakReference<Listener> listener = null; 

    public void doAction(String action, Listener listener) { 
     this.listener = new WeakReference<Listener>(listener); 
     doTheAction(action); 
    } 

    public void actionComplete() { 
    if (listener != null && listener.get() != null) 
      listener.onListen(); 

    } 
} 

public class AnotherClass { 
    ActionClass actioner = new ActionClass(); 
    void init() { 
     actioner.doAction("something", new Listener() { 
      onListened() { 
       Log.d("Tag", "Action complete!"); 
      } 
     }; 


    } 
} 

К сожалению, если есть опечатки/синтаксических ошибок, это было больше, значит быть псевдо-код.

В любом случае, много раз к тому времени, когда «Действие» будет завершено, WeakReference для слушателя будет GCed, хотя экземпляр «AnotherClass» все еще жив. Есть ли способ избежать этого?

+1

Почему вы используете 'WeakReference' вместо того, чтобы просто держаться за обычную ссылку? – chrylis

+0

В случае действия или фрагмента, например, если GC хочет GC, то я не хочу, чтобы ссылка на слушателя была единственной вещью, которая сохраняет ее. – StackOverflowed

+0

Это означает, что обратный вызов по существу бесполезен, поскольку клиентский код не может полагаться на его вызов. – chrylis

ответ

3

как в стороне, более чем в ответ, у Вас есть ошибка в вашем код:

if (listener != null && listener.get() != null) 
    listener.get().onListen(); 

Этот код содержит гонки conditition, поскольку GC может пожинать отношение между временем вы проверить его null и времени вы называете его. Его необходимо заменить на это:

if(listener != null) { 
    Listener l = listener.get(): 
    if(l != null) 
     l.onListen(); 
} 

Это предотвращает доступ к любому слушателю, имеющему ссылку в локальной переменной.

Кроме того, вы должны знать, что GC также может поддерживать Listener вокруг намного дольше, чем ваш AnotherClass в противном случае жив, так как нет никакой гарантии, когда он будет получен, но, я думаю, вы это знали.

+0

Отлично, отличная точка. Это похоже на строки 'if (getView()! = Null) {...... getView(). FindViewById (R.id.something) .setVisibility (View.GONE);}' – StackOverflowed

6

Пусть AnotherClass реализует прослушиватель или имеет закрытый экземпляр внутри. IE:

Listener myListener = new Listener() { 
    public void onListed() { 
    .... 
    } 
}; 

Ссылка AnotherClass слушатель будет держать свою ссылку в живых (пока у вас есть ссылки AnotherClass в вашей программе)

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