Политика конфиденциальностиКонтактыО сайтеОтзывыGitHubDonate
© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB

Немного об утечках памяти и способах их избежать

Memory leaks, garbage collection, Java

Что такое Утечки памяти (Memory leaks) в Андроид разработке ?

Приложение создает объекты, они лежат в памяти и не могут оттуда отчиститься после завершения своей работы.

Почему так происходит ?

Java имеет собственные средства очистки памяти от неиспользуемых элементов. Это garbage collection .

Сборщик мусора помечает все объекты, которые можно удалить, если на них нет ссылок. Memory leak - это как раз потерявшаяся ссылка, которая показывает, что объект удалить нельзя.

Сложность этого бага заключается в том, что до определенного времени его не видно и он может не мешать.
Есть хорошая цитата Бенджамина Франклина “Маленькая течь топит большой корабль." Утечки памяти съедают оперативную память приложения. Количество неочищенной памяти будет расти и однажды может привести к тому, что ваше приложение начнет тормозить и крашиться . Что приведет к недовольству пользователей и, скорее всего, приложение будет удалено...

Одно из самых опасных , когда программе теряется ссылка на view . Казалось бы, что такого, view маленькая на экране. Однако, стоит помнить, что у view есть ссылка на Activity (Fragment). A если ссылка на view не удалилась, то и Activity(Frsgment) тоже жива. A у Activity(Fragment) есть ссылки на все view, что есть на экране.

Как понять, есть ли утечки памяти ?

Отыскать мемори лики можно разными способами. Но самый простой - воспользоваться профайлером Android studio.

Порядок действий:

  • Запускаете проект
  • В нижней панели нажимаете "Profiler"
  • Выбираете "Memory"
  • Нажимаете "Force Garbage Collection" (затем нужно немного подождать)
  • Нажимаете "Dump Java heap"
  • Фильтруете список по необходимым классам
  • Смотрите количество объектов

На картинке выше видно, что имеется четыре объекта Activity . Это произошло, потому что программист позволил программе потерять ссылки на view . А пользователи очень любят поворачивать экран телефона. С каждой сменой ориентации активити пересоздавалась, а старая оставалась валяться в глубинах памяти.

Если вы хотите способ отлова утечек памяти поинтереснее, тогда предлагаю вам ознакомиться с библиотекой LeakCanary .

Как избежать утечек памяти ?

Вот несколько советов:

1. Не создавать статические ссылки на view. У статических полей жизненный цикл такой же, как у вашего приложения.

2. Не передавать ссылки в сущности, которые живут дольше, чем объект, который вы передали. Например: не стоит передавать в класс Runnable ссылки на View , так как новый поток продолжить жить даже после пересоздания активити.

public class LeakingRunnable implements Runnable {

    private View view;

    LeakingRunnable(View view){       // не делай так!
        this.view = view;
    }
    @Override
    public void run() {
        // do some work
    }
}

А как передавать view в Runnable ?

Использовать другие типы ссылок. В Java, кроме обычных "жестких ссылок" существуют другие "мягкие ссылки" и "слабые" . Правильно их называть:

  • WeakReference
  • SoftReference
  • Phantom Reference

Наличие "мягких ссылок" уже не будет мешать garbage collection удалять Acrivity. Подробнее почитать о них вы можете по ссылке: отличия между слабыми, мягкими, фантомными и обычными ссылками в Java

Без утечек памяти код выше выглядел бы так:

public class NoLeakingRunnable implements Runnable {

    @NonNull
    private final WeakReference<View> viewRef;

    public NoLeakingRunnable(@NonNull View view){
        this.viewRef = new WeakReference<>(view);         //делай так!
    }
    @Override
    public void run() {
        View view = viewRef.get();
        // do some work
    }
}  

3. Нужно делать внутренние классы Activity статическими. У внутреннего класса активити про обращении к view (и любым другим объектам) создаются ссылки на этот объект. И если внутренний класс живет дольше, чем активити, то появляется Memory leak.

В данной статье была рассказана лишь небольшая часть информации о том, что же такое утечки памяти в Андроид разработке и самые простые способы их избежать. Существует еще множество сложных ситуаций. Некоторые их них будут разобраны в следующих статьях. Подписывайтесь на новые статьи.

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
A
22 января 2019 г. 21:22
Allyonz

C++ - Тест 001. Первая программа и типы данных

  • Результат:40баллов,
  • Очки рейтинга-8
A
22 января 2019 г. 14:15
Alex

Qt - Тест 001. Сигналы и слоты

  • Результат:89баллов,
  • Очки рейтинга6
IO
20 января 2019 г. 18:39
Ivan Otreshko

C++ - Тест 003. Условия и циклы

  • Результат:0баллов,
  • Очки рейтинга-10
Последние комментарии
22 января 2019 г. 13:17
Евгений Легоцкой

Создайте тогда тему здесь на форуме в разделе Qt с выкладками кода и вашими попытками внедрения делегата, позже гляну или может кто-то ещё глянет из опытных пользователей.
I
22 января 2019 г. 13:13
IscanderChe

Не проще тогда использовать сразу кастомный делегат с чекбоксом? Я попробовал, но там засада в том, что чекбокс показывается только при щелчке на ячейку, а дефолтно показывается значение. Как ...
22 января 2019 г. 12:15
Евгений Легоцкой

Если будет не приемлемо потом, то тогда через кастомный Item Delegate нужно будет перерисовать ячейки в той колонке.
I
22 января 2019 г. 12:09
IscanderChe

Получилось приемлемо. Спасибо!Нюанс только в том, что поле рядом с чекбоксом не пропадает, оно просто пустое, что видно при выделении ячейки. Но этого достаточно.
22 января 2019 г. 11:50
Евгений Легоцкой

Переопределить метод data для той колонки и роли Qt::DisplayRole, чтобы в том случае возвращался QVariant() я так думаю... Но возможно, что у вас там будут нюансы, если вы туда чекбокс за...
Сейчас обсуждают на форуме
23 января 2019 г. 7:54
Михаиллл

Зарание спасибо.А еще на эту тему можно будет сделать статью. Это контент будет уникальным.
23 января 2019 г. 7:37
Евгений Легоцкой

Hello. Maybe the English will be better for you? I think russian is not native language for you, or did I mistake? Did I undesrtood rightly, that you mean this documentation ( ...
I
22 января 2019 г. 13:45
IscanderChe

Всем добрый день. Суть задачи: надо, чтобы в одной из колонок QTableView вместо хранимого в QSqlTableModel значения выводился чекбокс и при смене состояния чекбокса значения в базе тоже ...
M
22 января 2019 г. 13:15
Max-P85

Евгений, огромное спасибо, все работает!
Присоединяйтесь к нам в социальных сетях

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы