Чи міг компонент навігаційної арки створити помилковий позитивний витік пам'яті?


14

У мене є основні знання про витоки пам’яті та те, що може їх викликати. Тому я не розумію, чи є у мене проблема в коді чи це хибний позитив. Я не знаю, якою частиною коду я повинен поділитися, оскільки проект не малий. Але просто повідомте мене в коментарях, і я додам необхідний код.

Я використовую компонент арки навігації та дотримуюся схеми MVVM. Пізніше до розробки проекту я додав бібліотеку LeakCanary, і вона негайно почала видавати мені попередження про збережені випадки, коли я переходжу між екранами.

Проблема виникає, коли я додаю фрагменти до задньої стопки. З кожним доданим фрагментом до задньої стеки лічильник збережених екземплярів збільшується. Коли воно досягне порогового значення 5 LeakCanary скидає купу і надає звіт.

Але якщо я натискаю кнопку назад і повертаюсь до попередніх екранів, тоді лічильник збережених примірників зменшується і, зрештою, при поверненні на перший екран всі збережені екземпляри зникають.

Якщо я дивлюся на звіти про аналіз купи, це говорить, що змінна координаторLayout, яка є посиланням на CoordinatorLayoutxml, просочилася. Якщо я видаляю змінну та все її використання та запускаю програму ще раз, я бачу ту саму проблему, але тепер із іншою змінною, яка є посиланням на інший вигляд у xml. Я спробував видалити всі перегляди та їх використання, про які LeakCanary повідомив про протікання. Коли вона сказала, що a TextView, який просто використовується для встановлення тексту onViewCreatedі не використовується ніде більше, протікає, я почав сумніватися, що в моєму коді є проблема.

Я проаналізував виклики методу життєвого циклу фрагментами і зауважив, що коли я переходжу до нового екрана попереднього фрагмента, всі методи до включення onDestroyViewотримують виклики, але ні onDestroy. Коли я натискаю назад onDestroy, викликається фрагмент, який знаходився вгорі заднього стека, а лічильник збережених примірників зменшується.

Я підозрюю, що компонент Навігація зберігає примірник фрагмента, коли він знаходиться в задній стек, і LeakCanary розглядає це як витік.

Відповіді:


24

Ось так працюють фрагменти на задній стеці (а навігація просто використовує існуючі API-фрагменти): подання фрагмента знищується, але сам фрагмент не знищується - вони зберігаються в CREATEDстані, поки ви не натиснете кнопку назад і не повернетесь до фрагмента (після цього onCreateView()ви будете викликані знову, і ви перейдете назад до RESUMED).

Згідно з фрагментами: "Минуле, теперішнє" та "Майбутнє" , однією з майбутніх змін, що надходять до "Фрагменти", є вибір варіанту знищення фрагментів на задній стеці, а не двох окремих життєвих циклів. Це ще не доступно.

Вам потрібно анулювати свої посилання на представлення, onDestroyViewоскільки це ознака того, що подання системою Fragment більше не використовується, і його можна сміливо збирати сміттям, якщо воно не було для вашої подальшої посилання на Вид.


2
Чи вирішує проблему Android View Binding цю проблему? Я не можу знайти жодної документації щодо того, чи посилання на представлення перегляду прив'язки (можливо, сам об'єкт зв'язування) автоматично "обнуляється" в " onDestroyViewПерегляд прив'язки".
Тім Мальсід

3
@TimMalseed - вам потрібно самостійно зняти свою посилання на об'єкт зв’язування, нічого автоматичного не відбувається.
ianhanniballake

1
@Emmanuel - вам потрібно відмовитись від посилання на сам об'єкт зв'язування, оскільки він містить чітке посилання на представлення, якими він володіє.
ianhanniballake

1
@Emmanuel - ви завжди можете подати запит на функцію !
ianhanniballake

1
@Emmanuel - Я думаю, що це, безумовно, буде зміною поведінки (що може означати, що це окремий вибір прапора), але наявність правильного LifecycleOwner була б достатньою інформацією для того, щоб виправити цілу кількість проблем із пам'яттю.
ianhanniballake
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.