Android. Thread и Activity. Memory Leak
В ходе углубленного изучения многопоточности в Android встал вопрос.
Хранит ли Thread (Или любые другие Java объекты) ссылку на объект Activity, в котором он (Thread) был создан? Если так, то почему не возникает Memory Leak величиной в то самое Activity при повороте экрана к примеру.
Ответы (2 шт):
Если вы не будете сохранять в вашем Thread ссылки на Context или любые другие объекты которые хранят в себе ссылки на Context (таких как View), то не будет утечек.
Сам по себе Thread не может вообще хранить в себе ссылок на Context, так как он вообще не знает о существовании. Thread это сугубо Java класс, Android Framework для него неизвестная сущность. Утечки зачастую происходят из-за того, что те кто используют Thread передают какие-то данные обратно в Activity, а вот для этого как раз и необходимо хранить в себе Context. Именно поэтому и нужно заботиться о об остановки Thread-а при уничтожении Activity.
Объект хранит ссылку на сущность, в которой он создан если:
- реализован как внутренний (в том числе анонимный) класс в классе этой сущности
- ссылка на сущность передана туда явно и записана в поле объекта
Но поток сам по себе может быть источником утечки памяти.
Поскольку не уничтожается сборщиком мусора, пока он выполняется (запущен, но не завершён), даже если у нас нет на него ни одной ссылки.
Соответственно удерживается в памяти и всё, на что объект потока ссылается.
Утечь поток может очень просто:
// создали объект потока
new Thread(){
public boolean runnung = true;
public void run(){
// какой-то повторяющийся, ожидающий или длительно выполняющийся код
while(runnung){
// ...
}
}
}.start(); // запустили поток
// а ссылку-то на объект потока не сохранили
// дальше мы не можем его завершить, так не имеем к нему доступа
При повороте экрана мы тоже можем потерять поток, так как ссылка на него осталась в экземпляре активности, которая больше не доступна.
Поэтому нужно связывать работу потока с жизненным циклом активности (служб и ресиверов это тоже касается между прочим) - завершать потоки при её завершении.
Для загрузки данных, необходимых для показа в активности лучше использовать специальные решения, типа https://developer.android.com/topic/libraries/architecture/viewmodel , которые учитывают жизненный цикл и пересоздание активностей.
Если требуется выполнять задачу независимо от жизненного цикла активности, то стоит подумать об её реализации в службе.