English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Краткий анализ методов предотвращения переполнения памяти в Android

Этот пример рассказывает о методах предотвращения переполнения памяти в программировании на Android. Делимся с вами для вашего использования и обсуждения, подробности см. ниже:

 Виртуальная машина Android основана на регистрах Dalvik, максимальный размер стека обычно составляет 16M. Однако Android написан на Java, поэтому в значительной степени механизм памяти Android эквивалентен механизму памяти Java, и при начальном разработке могут возникнуть серьезные проблемы с ограничением памяти, такие как переполнение памяти. Когда мы не используем некоторые память, мы должны стараться избегать сохранения необходимых состояний на Android или других платформах, когда запущены другие программы, чтобы минимизировать проблемы с памятью, вызываемые死ыми процессами, и стараться освободить память при закрытии программы или сохранении состояния, чтобы улучшить плавность работы системы.

Основные аспекты памяти Android:

1. На платформе Android долгосрочное хранение ссылок на ресурсы может привести к тому, что некоторые память не может быть освободлена, что вызывает множество проблем с утечкой памяти. Например: Context (в дальнейшем提到的 Activity также относятся к Context), когда вам нужно сохранять состояние первой классовой объекты и передавать это состояние в другие классовые объекты, до того как удалить первую классовую объекты, вы должны сначала освободить объекты, которые получают это состояние. Необходимо отметить, что: в Java или Android механизме памяти перед тем как вершина узла может быть освобождена, должны быть гарантированы, что другие объекты не будут обращаться к нему. Давайте рассмотрим следующий фрагмент кода:

@Override
protected void onCreate(Bundle state) {
   super.onCreate(state);
   TextView label = new TextView(this);
   label.setText("Leaks are bad");
   setContentView(label);
}

Значение этого кода заключается в том, что мы загружаем экземпляр TextView в运行的 Activity (Context), поэтому, благодаря механизму GC переработки, мы знаем, что для освобождения Context, необходимо сначала освободить объекты, на которые он ссылается. Если этого не сделать, то при попытке освободить Context вы обнаружите, что будет大量的内存 переливания. Поэтому в случае неосторожности переполнение памяти может быть очень легко. Сохранение некоторых объектов также может привести к утечке памяти. Примерно, это может быть битмап (Bitmap), например: при вращении экрана разрушается текущее сохраненное состояние Activity, и создается новый Activity, пока новый Activity не будет сохранен. Давайте рассмотрим следующий фрагмент кода:

private static Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
if (sBackground == null) {
   sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}

Этот код очень быстрый, но неправильный. Утечка памяти легко может возникнуть при изменении ориентации экрана. Хотя мы можем не найти явного сохранения экземпляра Context, но когда мы подключаем изображение к просмотру, Drawable устанавливает обратный вызов для View, что означает, что в этом коде, когда мы рисуем TextView в активность, мы уже ссылаемся на эту Activity. Связь может быть представлена как: Drawable->TextView->Context.

Таким образом, когда вы хотите освободить Context, он все еще хранится в памяти и не освобождается.

Как избежать этой ситуацииОсновная проблема заключается в том, что最容易犯错 - это потоки. Не недооценивайте потоки, в Android они最容易 вызывать утечку памяти. Основная причина утечки памяти, вызываемой потоками, заключается в том, что их жизненный цикл трудно контролировать. Вот пример кода:

public class MyTest extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    new MyThread().start();
  }
  private class MyThread extends Thread{
    @Override
    public void run() {
      super.run();
      //Делать что-то
    }
  }
}

Код очень прост, но в Android появляются новые проблемы, когда мы переключаем экран просмотра (горизонтальный или вертикальный), и Activity создается заново. Мы представляем себе, что ранее созданная Activity будет аннулирована, но что на самом деле? Механизм Java не предоставляет нам такое же чувство, так как функция run не завершена, и поэтому MyThread не был уничтожен, а это означает, что Activity, на которую он ссылается (Mytest), также не была уничтожена, что привело к проблеме утечки памяти.

Некоторые предпочитают использовать предоставляемый Android AsyncTask, но на самом деле проблемы AsyncTask более серьезны, Thread появляется проблема утечки памяти только когда функция run не заканчивается, а AsyncTask использует ThreadPoolExecutor, и жизненный цикл объектов Thread, которые он создает, неопределен и не контролируется приложением, поэтому, если AsyncTask является внутренним классом Activity, утечка памяти возникает легче.

Основные методы улучшения проблем с потоками:

① Перенести внутренний класс потока в статический внутренний класс.
② В программе尽量使用弱引用保存Context.

2. Проклятый Bitmap...

Bitmap - это очень плохой объект, для объекта памяти, если он занимает много памяти, и когда он exceeds системные ограничения памяти, проблема утечки памяти становится очевидной...
Решение проблемы Bitmap заключается в том, чтобы минимизировать сохранение его в памяти или уменьшить его разрешение. В многих случаях, так как у нас очень высокие разрешения изображений, а для размеров экрана мобильных телефонов нам не всегда нужны такие высокие разрешения, мы можем сначала уменьшить разрешение изображения перед выполнением исходных UI-операций.

Если не нужно сохранять ссылку на объект Bitmap, можно использовать soft reference в качестве замены. Примеры кода можно найти на google.

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

Первый: не следует хранить ссылки на Context в долгосрочной перспективе (если необходимо ссылаться на Context, следует поддерживать一致性 жизненного цикла между ссылкой и объектом).

Второй: если необходимо использовать Context, лучше использовать ApplicationContext вместо Context, так как у него более долгий жизненный цикл, и в случаях использования он не вызывает проблем с утечкой памяти

Третий:在不控制对象生命周期的前提下,尽量避免在Activity中使用static变量。尽量使用WeakReference代替static。

Четвертый:垃圾回收器并不能保证准确回收内存,因此在使用所需内容时,主要应关注对象的生命周期以及及时释放不再需要的对象。尽量在Activity的生命周期的结束阶段,在onDestroy方法中释放我们引用的其他对象,例如:cursor.close()。

На самом деле, мы можем использовать меньше кода для выполнения программ в wielu аспектах. Например, мы можем использовать больше 9patch изображений и т.д. Есть много мелких моментов, которые можно открыть и исследовать, чтобы найти больше проблем с памятью. Если мы сможем следовать принципу "творец создает, творец разрушает" в C/C++, то наше управление памятью не будет хуже, чем в Java или GC-механизме Android, и мы сможем лучше контролировать память, что сделает работу нашего телефона более плавной.

Читатели, интересующиеся дополнительной информацией о разработке Android, могут ознакомиться с нашими статьями на тему: "Суммарные советы по памяти и кэшу в разработке Android", "Введение и продвинутый учебник по разработке Android", "Сборник советов и методов по отладке и решению проблем в разработке Android", "Сборник советов по работе с мультимедийными данными в Android (аудио, видео, запись и т.д.)", "Сборник методов использования основных компонентов в Android", "Сборник методов использования View в Android", "Сборник методов использования layout в Android" и "Сборник методов использования элементов управления в Android".

Надеюсь, что описание в этой статье поможет вам в разработке программ Android.

Заявление: содержимое статьи взято из Интернета, авторские права принадлежат соответствующему владельцу, материал предоставлен пользователями Интернета по своей инициативе, сайт не имеет права собственности, материал не был отредактирован вручную, и сайт не несет ответственности за связанные с этим法律责任. Если вы обнаружите материалы,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (во время отправки письма замените # на @) для сообщения о нарушении и предоставьте соответствующие доказательства. При подтверждении факта нарушения сайт незамедлительно удаляет涉嫌侵权的内容.

Вам может понравиться