Java - это тип языка сбора мусора. Его преимущество состоит в том, что разработчикам не нужно намеренно управлять распределением памяти, что снижает вероятность того, что приложения будут сбоями из -за локальных неисправностей сегментации, и предотвращает разморочную память сжимать стек (куча). Поэтому написанный код более безопасен.
К сожалению, в Java все еще много логических утечек, которые подвержены утечке памяти. Если вы не будете осторожны, ваше приложение для Android может легко тратить память о нем, что в конечном итоге приведет к тому, что выброс ошибки заканчивается (вне памяти, OOM).
1. Причина общей утечки памяти заключается в том, что когда все ссылки на объект были выпущены, объект не был выпущен. (Примечание переводчика: курсор забыл закрыть и т. Д.)
2. Причина утечки логической памяти заключается в том, что когда приложению больше не требуется этот объект, все ссылки на объект не были выпущены.
Если у вас сильная ссылка на объект, сборщик мусора не может переработать объект в памяти.
В разработке Android наиболее вероятной проблемой утечки памяти является контекст. Например, контекст деятельности содержит большое количество ссылок на память, такие как иерархии просмотра и другие ресурсы. Как только контекст протекает, он также означает утечку всех объектов, на которые он указывает. Android -машины имеют ограниченную память, и слишком много утечек памяти может легко привести к OOM.
Обнаружение логической утечки памяти требует субъективного суждения, особенно жизненный цикл объекта неясно. К счастью, активность имеет четкий жизненный цикл, и легко найти причину утечки. Activity.Ondestroy () рассматривается как конец жизни деятельности. Программно, это должно быть уничтожено, или система Android должна перерабатывать эту память (примечание переводчика: когда память недостаточно, Android будет перерабатывать невидимые действия).
Если этот метод выполнен, все еще существует сильная ссылка на деятельность в стеке, и сборщик мусора не может пометить его как переработанную память, и наша первоначальная цель - переработать его!
Результатом является то, что деятельность выживает вне его жизненного цикла.
Активность является тяжелым объектом и должна обрабатывать систему Android. Однако утечки логической памяти всегда случаются непреднамеренно. (Примечание переводчика: я однажды попробовал деятельность, которая вызвала утечку памяти 20 м). В Android есть только два ловушки, которые приводят к потенциальным утечкам памяти:
Статическая переменная глобального процесса (процесс-глобал). Этот монстр, который игнорирует состояние применения и имеет сильную ссылку на деятельность.
Потоки, которые живут вне жизненного цикла активности. Никакие сильные ссылки на деятельность не были очищены.
Проверьте, столкнулись ли вы в следующих ситуациях.
1. Статическая деятельность
Переменная статической активности определяется в классе, а экземпляр выполнения в настоящее время назначается этой статической переменной.
Если эта статическая переменная не будет очищена после окончания жизненного цикла активности, это вызовет утечку памяти. Поскольку статические переменные проходят через жизненный цикл этого приложения, просочившаяся деятельность всегда будет существовать в процессе подачи заявления и не будет собираться коллекционером мусора.
Статическая активность активности; void setStaticActivity () {Activity = this;} view Sabutton = findViewById (r.id.sa_button); Sabutton.setonClickListener (new View.onclickListener () {@Override public void onclick (view v) {setStaticActivity (); nextActivity ();}});2. Статические виды
Подобные ситуации могут произойти в режиме Синглтона, и если активность часто используется, практично сохранить экземпляр в памяти. Как упоминалось ранее, навязывание жизненного цикла деятельности довольно опасно и ненужна, и это все равно не может быть сделано.
Специальный случай: если инициализация представления потребляет много ресурсов и остается неизменной в течение жизненного цикла активности, ее можно превратить в статическую и загруженную на иерахи. Таким образом, когда деятельность уничтожается, ресурс должен быть выпущен. (Примечание переводчика: память не выпускается в примере кода. Просто нулевой этот статический вид, но она все еще не рекомендуется использовать метод статического представления)
статический вид; void setStaticView () {view = findViewById (r.id.sv_button);} view svbutton = findviewbyid (r.id.sv_button); svbutton.setonclicklistener (new view.onclicklistener () {@override putual onclick (view v) {setStaticView (););););3. УНАЧЕНИЕ КЛАССОВ
Продолжайте, предполагая, что в деятельности есть внутренний класс, что может улучшить читаемость и инкапсуляцию. Если мы создадим внутренний класс и придерживаемся ссылки на статическую переменную, поздравляем, утечка памяти недалеко от вас (примечание переводчика: пусто, когда разрушается, UM).
частный статический объект внутренний; void createInnerClass () {class innerclass {} inner = new InnerClass ();} Просмотреть icbutton = findViewByid (r.id.ic_button); iCbutton.setonClickListener (new View.OnclickListener () {@Override public void onclick (view v) {createinnerClass (););););););););););););Одним из преимуществ внутренних классов является то, что они могут получить доступ к внешним классам. К сожалению, причина утечек памяти заключается в том, что внутренние классы содержат сильные ссылки на внешние экземпляры класса.
4. анонимные классы
Точно так же анонимные классы также поддерживают ссылки на внешние классы. Таким образом, утечки памяти легко произойти, когда вы определяете анонимный асинкек в своей деятельности. Когда асинхронная задача выполняет трудоемкую задачу в фоновом режиме, это, к сожалению, управляется (примечание переводчика: выходы пользователя, переработка системы), этот экземпляр действия, удерживаемый Asynctask
void startAsynctask () {new asynctask <void, void, void> () {@Override Protected void doinbackground (void ... params) {while (true); }} .execute ();} super.oncreate (savedInstanceState); setContentView (r.layout.activity_main); view aicbutton = findviewbyid (r.id.at_button); aicbutton.setonclicklister (new view.onclicklistener () { @@override public startAsynctask ();5. ХАРС
Точно так же, определите анонимный запуск и выполните его с помощью анонимного класса. Внутренний класс, который будет иметь неявную ссылку на внешний класс и передается в Quembreaue of the Handler Office Ofeue. Экземпляр деятельности не будет разрушен до тех пор, пока сообщение сообщения не будет обработано, что приведет к утечке памяти.
void createHandler () {new Handler () {@Override public void handlemessage (сообщение сообщений) {super.handlemessage (message); } }.postDelayed(new Runnable() { @Override public void run() { while(true); } }, Long.MAX_VALUE >> 1);}View hButton = findViewById(R.id.h_button);hButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {createHandler ();6.threads
Мы еще раз показываем утечки памяти через нить и Timertask.
void spawnthread () {new Thread () {@Override public void run () {while (true); }} .start ();} view tbutton = findViewById (r.id.t_button); tbutton.setonClickListener (new view.onclickListener () {@Override public void Onclick (view v) {spawnthread (); lexationActivity ();}});7.timertask
До тех пор, пока это экземпляр анонимного класса, независимо от того, находится ли он в потоке работников или нет, он содержит ссылку на деятельность, что приведет к утечке памяти.
void shaduleTimer () {new Timer (). Prade (new timertask () {@override public void run () {while (true);}}, long.max_value >> 1);} Просмотр ttbutton = findviewbyid (r.id.tt_button);} ttbutton.setonclicklister (r.id.tt_button); void onclick (view v) {swarduletimer ();8. Менеджерсензор
Наконец, системные службы могут быть получены через context.getSystemservice (int name). Эти услуги работают в своих соответствующих процессах, помогая приложениям обрабатывать фоновые задачи и аппаратные взаимодействия. Если вам нужно использовать эти услуги, вы можете зарегистрировать слушателей, что приведет к тому, что служба содержит ссылку на контекст. Если эти слушатели не будут вычеркнуты при уничтожении деятельности, это вызовет утечки памяти.
void RegisterListener () {SensorManager sensormanager = (sensormanager) getSystemservice (sensor_service); Датчик датчика = sensormanager.getDefaultsensor (sensor.type_all); sensormanager.registerlistener (это, сенсор, sensormanager.sensor_delay_fastest);} Просмотр smbutton = findViewByID (r.id.sm_button); smbutton.setonClickListener (new view.onclicklistener () {@Override vility void onclick (view v) {regiredLister (););Суммировать
Увидев так много примеров, которые могут привести к утечкам памяти, легко съесть всю память о вашем телефоне, привести к сбору мусора и обработки чаще, и даже в худшем случае это приведет к OOM. Операции по сбору мусора дороги и могут привести к видимым лагам. Поэтому обратите внимание на удерживаемую справочную цепочку при создании экземпляров и часто выполняйте проверки утечки памяти.