Невидимі лики ( Android , memory management )
Дано: Android аплікейшн з аудиторією 10 млн осіб. Crashlytics для трекінгу крешей .
Топ 1 % крешей виглядають так: або так: чи ще десятком різних уявлень , але всі вони - OutOfMemory креши . Була проведена робота з аналізу існуючих memory leaks в додатку , і всі вони були усунені. Щастя наступило , але було недовгим . Крешей стало менше , але вони не пішли. Кардіограма студії: Дамп Хіпа в Memory Analyzer tool ( www.eclipse.org/mat/ ) Монітор спокійний: adb shell dumpsys activity activities com.app_name | grep " Running activities " -A 30 | head -30 каже : « Узбагойся » : Task # 4 - запущена всього одна активують . Але креши щось не пішли ... Змушує замислитися . Добре, що є розумні люди в різних Гугля , які пишуть розумні статті на зразок цієї . Подивимося , що говорить :adb shell dumpsys meminfo com.app_name Після хвилини роботи додатку при одній відкритій активують в стеці : Wow ! 560 views та 8 activities ... Wow , чорт забирай ... щось тут не так ! Починаємо бісектіть код в живій активують . Результат : 1 . Найден код в стилі :
mHomeView.postDelayed ( new Runnable ( ) { Override public void run ( ) { bla - bla - bla } } ,время_в будущем_АКТУАЛЬНОЕ_после закритія_актівіті ) ; Здавалося б , все в порядку - якщо активують дестроітся , його в'ю , які не тримаються чимось зовні, повинні знищитися теж , попередньо почистивши колбек . Але не тут- то було. Даний код призводить до витоку всій активують . Лікується або виносом runnable в мембер класу з подальшим видаленням , або перенесенням логіки в mHandler = new Handler (); ... mHandler.postDelayed ( new Runnable ( ) { Override public void run ( ) { ... } } , то_же_время ) ; з очищенням у вигляді mHandler.removeCallbacksAndMessages ( null ) ; в onDestroy або onStop . Хоча по суті postDelayed на в'ю і хендлер повинні бути еквівалентні , якщо вірити шановним людям в світі Android. 2 . Деякий час тому один достойник індуської національності укрутив 3rd - party бібліотеку для реалізації shimmer ефекту ( glow над текстом) . Щось на зразок https://github.com/RomainPiel/Shimmer-android Все працює відмінно . Видимих ??ликів немає. У коді біблітекі знайдений наступний код: mAnimator = ObjectAnimator.ofFloat ( shimmerView , " gradientX " , fromX , toX ) ; mAnimator.setRepeatCount ( mRepeatCount ) ; mAnimator.setDuration ( mDuration ) ; ... mAnimator.start (); Виглядає підозріло :
- динамічна установка значень в'ю через Рефлекшн якимось делегатом ;
- передаємо в'ю кудись в дивного вигляду функцію. В коді фреймворка в класі ObjectAnimator робота з в'ю виглядає безпечно : mTarget = target == null ? null : new WeakReference & lt ; Object & gt ; ( target ) ; ... Nullable public Object getTarget ( ) { return mTarget == null ? null : mTarget.get (); } ... final Object oldTarget = getTarget (); if ( oldTarget ! = target ) { ... } Витоків бути не повинно ... В процесі руйнування досліджуваної активують викликається mAnimator.cancel ( ) , який повинен зупинити анімацію . Шок : Анімація НІКОЛИ не зупиняється. Були випробувані різні методи види: mAnimator.cancel (); mAnimator.end (); shimmerView.clearAnimation (); та інші збочення . Не допомогло нічого . Не ми одні такі :
Модифікуємо код , щоб позбутися від передачі в'ю в аніматор . Вуаля ! Memory leaks gone ! Точна причина , чому аніматор не зупиняється , в нашому випадку не встановлена ??, і можливо , інші додатки страждати від цього не будуть , але факт дуже неприємний. Висновки :
- Не вір очам своїм . Що стосується пам'яті - на жаль , різні інструменти показують різні речі , і невідомо , чому вірити .
- Маніпулювати явно або неявно об'єктами UI фреймворка ( в нашому випадку views ) - зазвичай дуже погана ідея .
- При розробці додатків для Android перевіряйте висновок : watch -n 1 adb shell dumpsys meminfo com.app_name Судячи з усього , це єдиний об'єктивний джерело метрик пам'яті та об'єктів UI фреймворка , на який можна покладатися при розробці . Удачи !
Опубліковано: 19/11/14 @ 07:30
Розділ Різне
Рекомендуємо:
За рішенням інвесторів український GlobalLogic змінив керуючого директора
Як вибрати тематику англомовного сайту
Как добраться до вершин?
Результати опитування про роботу за кордоном
Як реанімувати старий безнадійний проект. Частина 2 : Тимбилдинг