Управление памятью Android в жизненном цикле деятельности
Мой вопрос немного сложный.
Я хочу понять, как приложение обрабатывает ресурсы (особенно изображения для фона, кнопки и т.д.), когда действие запущено, а затем приостановлено.
Например, я запускаю Activity A, он отображает все изображения на экране, ест его память, затем запускается другое действие B и A приостанавливается. Что происходит со всеми изображениями, ресурсами и т.д.? Когда они освобождаются? Как я могу контролировать их? Должен ли я не сохранять активность А в памяти и удалять ее из стека активности?
Если вам нужны разъяснения по моим вопросам, напишите мне!
Спасибо заранее!
Danail
Ответы
Ответ 1
Активность не освобождает ресурсы до ее завершения. Но в большинстве случаев это не должно быть проблемой для вас. На мой взгляд, вы не должны добавлять свое собственное управление ресурсами и усложнять свой код в большинстве случаев.
Но если вы действительно думаете, что ваше приложение может быть не в памяти, вы должны проверить его с помощью MAT. Проблемы с памятью могут быть вызваны утечками памяти, а не интенсивным использованием памяти.
В конце концов, когда вы абсолютно уверены, что вам нужно что-то сделать для сокращения использования памяти, вы можете сделать некоторую оптимизацию памяти. Например, вы можете сохранить объекты, потребляющие память (например, большие изображения), в локальное хранилище в onStop()
и загрузить их в onStart()
. Я думаю, что использование onPause()
/onResume()
для этой цели - плохая идея, потому что действие частично или даже полностью видимо.
В теории вы можете даже уничтожить все свои виджеты в onStop()
и восстановить их в onStart()
, но это может сделать ваше приложение слишком медленным. И, конечно же, в этом случае сохранение состояния должно осуществляться вами.
Завершающая деятельность может показаться хорошей идеей, но я думаю, что это не так. Во-первых, это замедляет работу. Во-вторых, вы должны сами управлять стеком деятельности и состоянием деятельности.
Например, Activity A запускает Activity B. Итак, Activity B должен знать, что делать, когда пользователь нажимает кнопку "Назад". Когда пользователь нажимает кнопку "Назад", вы должны запустить Activity A и восстановить его состояние. Но что, если пользователь прекратит это приложение. В этом случае вы должны инициализировать Activity A с состоянием по умолчанию. Итак, вы должны реализовать много дополнительной логики.
В заключение я повторю основную идею еще раз: не оптимизируйте использование памяти, если вы не уверены, что вам нужно!
Ответ 2
Итак, мы имеем следующую ситуацию:
A > onCreate
A > onStart
A > onResume
A > Use up a load of memory (A could even use up too much and crash)
A > Launch activity B
B > onCreate
A > onPause
B > onStart
A > onStop
B > onResume
B > Use up a load of memory
Если B использует достаточное количество памяти, система Android будет убивать активность A (вы заметите, что методы onPause и onStop A уже вызваны, так что ему уже предоставлена возможность сохранить его состояние)
Если вы затем нажмете кнопку "Назад", система Android снова запустит операцию "А" (и если она умна, она должна запомнить ее в последнем состоянии), поэтому похоже, что с пользователем ничего не случилось.
Итак, чтобы быть немного понятнее: если вы запустите B, а затем закончите A, B по существу просто заменит A в стеке действий и нажав кнопку "Назад" в действии B, вы выйдете из своего приложения и не вернуться к активности A.
Если, с другой стороны, вы запускаете B, не заканчивая A, тогда нажатие кнопки возврата в B будет возвращает вас к A. В то время как активность A находится в фоновом режиме, она может быть убита для восстановления памяти, но Android будет воссоздавать его по мере необходимости, когда пользователь переходит через стек действий.
Также, если у вас есть в кэшах памяти из нескольких объектов (например, растровые изображения/чертежи), верните свою коллекцию SoftReferences, чтобы GC мог их очистить, если она работает с низким объемом памяти.
Ответ 3
Вы должны создать свое приложение так, чтобы его использование было низким, но вы можете рассчитывать на фреймворк, который лучше всего подходит для управления памятью. Таким образом, не стоит слишком много работать с удалением неиспользуемого материала, только в случаях, когда очевидно, что ваше приложение слишком много памяти.
Когда доступная память опускается, инфраструктура остановится и удалит действия и службы, которые не связаны с текущей задачей. Если ваше приложение потребляет еще больше памяти, инфраструктура остановит ваши действия, которые находятся в фоновом режиме. Затем идут службы, связанные с вашим приложением, и последняя, которая будет завершена, будет текущей.
Когда среда останавливает активность, она ведет запись стека активности, намерения, используемые для запуска активности и пакета, возвращаемого onSaveInstanceState(), поэтому он может воссоздать последнее известное состояние действий. Кроме того, структура может выгружать неиспользуемые ресурсы (чертежи и т.д.), Когда они не используются, и перезагружать их при необходимости.
Ответ 4
Прежде чем ответить на ваши вопросы, у меня есть некоторые факты для обсуждения.
-
В соответствии с жизненным циклом Activity, если мы назовем finish()
, тогда вызываем onStop()
и, наконец, onDestroy()
, который устраняет эту активность для коллекции мусора и удаляет из Activity Stack Android.
-
Android поддерживает контейнер Drawable для проектирования и отображения активности на экране. Поэтому, если вы отключите доступный кэш в Activity onCreate()
.
Итак, лучше всего отключить кэшируемый ресурс onCreate
следующим образом:
LinearLayout v = (LinearLayout) findViewById(R.id.mainLayout);
v.setDrawingCacheEnabled(false);
и вызвать finish();
на onPause()
;
Ответ 5
У вас очень мало контроля над памятью при написании кода Java. Это хорошо для большинства случаев. На самом деле большинство приложений не нужно беспокоиться о памяти.
Чтобы ответить на ваш вопрос, весь объект для активности A будет по-прежнему находиться в памяти, когда он будет приостановлен. VM запускает GC, когда ему нужен ресурс.