Android. Thread и Activity. Memory Leak

В ходе углубленного изучения многопоточности в Android встал вопрос.

Хранит ли Thread (Или любые другие Java объекты) ссылку на объект Activity, в котором он (Thread) был создан? Если так, то почему не возникает Memory Leak величиной в то самое Activity при повороте экрана к примеру.


Ответы (2 шт):

Автор решения: Sergei Buvaka

Если вы не будете сохранять в вашем Thread ссылки на Context или любые другие объекты которые хранят в себе ссылки на Context (таких как View), то не будет утечек.

Сам по себе Thread не может вообще хранить в себе ссылок на Context, так как он вообще не знает о существовании. Thread это сугубо Java класс, Android Framework для него неизвестная сущность. Утечки зачастую происходят из-за того, что те кто используют Thread передают какие-то данные обратно в Activity, а вот для этого как раз и необходимо хранить в себе Context. Именно поэтому и нужно заботиться о об остановки Thread-а при уничтожении Activity.

→ Ссылка
Автор решения: woesss

Объект хранит ссылку на сущность, в которой он создан если:

  1. реализован как внутренний (в том числе анонимный) класс в классе этой сущности
  2. ссылка на сущность передана туда явно и записана в поле объекта

Но поток сам по себе может быть источником утечки памяти.
Поскольку не уничтожается сборщиком мусора, пока он выполняется (запущен, но не завершён), даже если у нас нет на него ни одной ссылки.
Соответственно удерживается в памяти и всё, на что объект потока ссылается.
Утечь поток может очень просто:

// создали объект потока
new Thread(){
    public boolean runnung = true;
    public void run(){
        // какой-то повторяющийся, ожидающий или длительно выполняющийся код
        while(runnung){
            // ...
        }
    }
}.start(); // запустили поток
// а ссылку-то на объект потока не сохранили
// дальше мы не можем его завершить, так не имеем к нему доступа

При повороте экрана мы тоже можем потерять поток, так как ссылка на него осталась в экземпляре активности, которая больше не доступна.
Поэтому нужно связывать работу потока с жизненным циклом активности (служб и ресиверов это тоже касается между прочим) - завершать потоки при её завершении.
Для загрузки данных, необходимых для показа в активности лучше использовать специальные решения, типа https://developer.android.com/topic/libraries/architecture/viewmodel , которые учитывают жизненный цикл и пересоздание активностей.
Если требуется выполнять задачу независимо от жизненного цикла активности, то стоит подумать об её реализации в службе.

→ Ссылка