Утечка просто означает, что объект класса больше не используется, но система не может восстановить память, в которой они живут (куча памяти). Это происходит потому, что существует хотя бы одна сильная ссылка, сохраняющая ссылку на объект.
Вернуться к вашему делу.
// Setting the listener
Utility.getInstance().setListener(new Utility.UpdateListener() {
@Override
public void onUpdate() {
Log.d("ListenerLeak", "Something is updated!");
}
});
Вы создаете анонимный внутренний класс (класс без имени), который реализует интерфейс Utility.UpdateListener
, и вы также создаете анонимный объект анонимного внутреннего класса, используя ключевое слово new
, но не сохраняете никаких ссылок на объект.
В Java, когда вы объявляете внутренний класс, он сохраняет ссылку на внешний класс (в данном случае ListenerLeak
активность).
// Starting a background thread
Utility.getInstance().startNewTread();
В методе startNewTread
вы создаете и запускаете фоновый поток.
new Thread (new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000 * 10);
if (listener != null)
listener.onUpdate();
} catch (InterruptedException e) {
Log.d("Utility", e.getMessage());
}
}
}).start();
Снова в этом классе вы создаете анонимный класс, который реализует интерфейс Runnable
, и вы создаете анонимный объект класса Thread
. В результате поток сохраняет ссылку на класс Utility
. Это ссылочная цепочка
Background Thread -> Utility -> Listener -> ListenerLeak (the activity)
Когда пользователи нажимают кнопку возврата на активности. В это время активность используется дольше, и система может восстановить память, в которой она находится. К сожалению, потому что фоновый поток все еще хранит ссылку на него, поэтому система не может восстановить память. В результате происходит утечка.
Решение: Когда пользователи нажимают клавишу возврата, прежде чем уничтожить действие, система вызовет метод onDestroy. В этом методе вы должны удалить ссылку из фонового потока на это действие.
@Override
protected void onDestroy() {
Utility.getInstance().setListener(null);
super.onDestroy();
}
Вот цепочка ссылок
Background Thread -> Utility -> Listener -> null (point to nothing)
И теперь нет строгих ссылок на действия, поэтому система восстановит память, и утечки не будет.