Невидимі лики (Android, memory management), DOU
Дано: Android аплікейшн із аудиторією 10 млн осіб. Crashlytics для трекінгу креші.
Топ 1% крешей виглядають так:

або ще десятком різних уявлень, але всі вони — креші OutOfMemory.
Була проведена робота з аналізу існуючих memory leaks у додатку, і всі вони були усунені. Щастя настало, але було недовгим. Крішків поменшало, але вони не пішли.

Дамп хіпу в Memory Analyzer tool (www.eclipse.org/mat/)


Task #4 - запущена лише одна активіті. Але креші не пішли. Змушує задуматися.
Добре, що є розумні люди в різних гуглах, які пишуть розумні статті на кшталт цієї.
Подивимося, що каже:
Після хвилини роботи програми при одній відкритій активіті в стеку:

Wow! 560 views і 8 activities. Wow, чорт забирай. щось тут не так!
Починаємо бісектити код у живій активіті.
Результат:
1. Знайдено код у стилі:
час_в майбутньому_АКТУАЛЬНИЙ_після закриття_активіті);
Здавалося б, все гаразд — якщо активіти дебудується, його в'ю, які не тримаються чимось ззовні, повинні знищитись теж, попередньо почистивши колбеки. Але не тут було. Цей код призводить до витоку всієї активіті. Лікується або виносом runnable в мембер класу з подальшим видаленням, або перенесенням логіки в
з очищенням у вигляді
в onDestroy або onStop. Хоча насправді postDelayed на в'ю і хендлер повинні бути еквівалентні, якщо вірити шановним людям у світі Android.
2. Деякий час тому одна шановна людина індуської національності вкрутила 3 rd -party бібліотеку для реалізації shimmer ефекту (glow над текстом). Щось на зразокhttps://github.com/RomainPiel/Shimmer-android

Все працює чудово. Видимих ликів немає. У коді бібліотеки знайдено наступний код:
Виглядає підозріло: - динамічна установка значень в'ю через рефлекшн якимсь делегатом; - передаємо в'ю кудись у дивного виду функцію.
У коді фреймворку в класі ObjectAnimator робота з в'ю виглядає безпечно:
Витоків не повинно бути.
У процесі руйнування досліджуваної активіти викликається mAnimator.cancel() , який має зупинити анімацію.
Шок: Анімація НІКОЛИ не зупиняється. Були випробувані різні способи виду:
та інші збочення. Не допомогло нічого.
Модифікуємо код, щоб позбавитися передачі в'ю в аніматор. Вуаль! Memory leaks gone!
Точна причина, чому аніматор не зупиняється, у нашому випадку не встановлена, і, можливо, інші програми страждати від цього не будуть, але факт дуже неприємний.
Висновки: — Не вір очам своїм. Що стосується пам'яті - на жаль, різні інструменти показують різні речі, і невідомо, чому вірити. - маніпулювати явно або неявно об'єктами UI фреймворку (в нашому випадку views) - зазвичай дуже погана ідея. - При розробці додатків для Android перевіряйте висновок:
Зважаючи на все, це єдине об'єктивне джерело метрик пам'яті та об'єктів UI фреймворку, на яке можна покладатися при розробці.