Активность как слушателя и утечки памяти - PullRequest
2 голосов
/ 23 ноября 2010

У меня есть следующая структура для моего приложения: 1. Сетевой поток, который работает в фоновом режиме (очередь) для выдачи запроса и получения асинхронных ответов.Поток запускается и останавливается в объекте приложения, поэтому он выходит из всего приложения.2. DataManager, который также является членом Application и имеет различные DataManager для типов данных, которые я извлекаю из сети.сам диспетчер данных является прослушивателем ответов из сети, поэтому он безопасен до тех пор, пока само приложение не умрет.3. это проблемная часть.Некоторые из моих адаптеров и часть моих действий являются DataListeners для моих DataManager, это означает, что диспетчер данных сохраняет ссылку на них.

Когда происходит телефонный звонок или какое-либо другое событие телефона, я заметил, что действиеобычно находится в состоянии паузы и не уничтожается и поэтому получает мои события, что нормально.проблема начинается, когда пейзаж \ портрет меняется.Так как я сохраняю ссылку на действие в связанном с Приложением объекте, действие не может быть уничтожено с одной стороны, НО событие все еще попадает в слушатель, только неправильное ... В принципе, я могу исправить эту проблему, удаливслушатель в onDestroy и сохраняющая логическая конфигурация, чтобы сказать мне, что запрос был уже готов, и мне просто нужно поставить слушателя и попытаться получить данные из диспетчера данных.

Однако :-) мне было интересно, как Androidобычно обрабатывает эти случаи, если, например, это была запущенная служба.или если Служба является локальной службой, которая использовала Bound и передавала Activity в качестве прослушивателя сетевого события, происходит то же самое, пока слушатель не будет удален, Activity утечка и продолжает работать, но без него невозможнополучать обратные вызовы из сети ... Намерение требует сериализации и десериализации данных, которые могут быть тяжелыми (например, растровые изображения?)

И в любом случае, если я отправляю намерение при каждом получении, которое я получаю, как мне получитьнамерение к Деятельности (я знаю о getIntent, но если я получу другой, не связанный, получу ли я его как «событие»?)

Ответы [ 3 ]

1 голос
/ 23 ноября 2010

Разработка Android довольно отличается от других платформ (например, BlackBerry). Я не могу дать вам быстрое решение серебряной пули, однако вот мои мысли по этому поводу:

Некоторые из моих адаптеров и часть моего Деятельности являются DataListeners для моего DataManager, это означает, что данные менеджер хранит ссылку на них.

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

Также следует помнить, что Application экземпляр подкласса не всегда существует в течение всего сеанса приложения (сеанс с точки зрения пользователя). Если ваше приложение работает в фоновом режиме, например, из-за входящего телефонного звонка, весь ваш процесс может быть уничтожен. Подробнее здесь . Как только ваш подкласс Application содержит некоторое состояние, которое не сохраняется, если процесс завершен, вы можете ошибочно ожидать, что ваши дескрипторы будут указывать на некоторые ненулевые объекты. Однако после перехода на передний план (и восстановления процесса) они могут быть просто нулевыми, поскольку ОС создала новый экземпляр Application подкласса.

1 голос
/ 23 ноября 2010

Из того, что я понял, на Android принято удалять себя из списков слушателей, когда активность уничтожается. Это своего рода ошибка, но я думаю, что это общепринятый способ сделать это.

Можно предположить, что ваша служба принимает только одного прослушивателя, который может соответствовать или не соответствовать вашему случаю, и когда действие возобновляет свою регистрацию в DataManager, будет перезаписано старое действие, которое, в свою очередь, будет собирать мусор. Недостатком является то, что вы не освобождаете память активности, если она уничтожена, но служба работает, поэтому, вероятно, лучше просто удалить активность из слушателей.

0 голосов
/ 31 января 2011

Хорошо, позвольте мне более подробно описать проблему и решение, которое я нашел.Проблема: у меня есть поток службы \ сети, который должен уведомлять действия, которые отправляют запросы через него, о том, что запрос или ошибка поступили асинхронно.Использование Pattern Listener требует, чтобы я настроил слушателя до или когда я отправляю запрос следующим образом:

mNetService.setRequest(request, this); 

, где это Activity, которая реализует мой интерфейс слушателя.Но для этого необходимо, чтобы я удалил прослушиватель из службы в onDestroy и возвратил прослушиватель, если я когда-либо отправил запрос обратно в onCreate \ onResume, но ответ также может прийти именно тогда, когда действие не прослушивается (ландшафт \ портрет)событие), которое требует, чтобы я оставил сообщение об ошибке \ ответ в службе до тех пор, пока кто-нибудь не поднимет его и не сбросит.

Решение, которое я нашел: использование Broadcasts и BroadcastReciever.это только часть решения, но она позволяет прослушивать широковещательные рассылки (которые могут быть специфическими для определенного типа класса, означающего активность) и действия.Поскольку все мои действия наследуют базовый класс Activity, я сделал, что у них всех есть внутренний класс BroadcaseReciever, который прослушивает определенные действия в своем фильтре.Если я включаю прослушивание в C'or моей деятельности, слушатель будет зарегистрирован в onResume и отменен в onPause.Если слушатель получает событие onRectained, он вызовет метод в Activity (который я могу переопределить в моей конкретной активности) и передаст ему полученное намерение, которое может содержать все данные из ответа.

Единственное пропущенноеЧто происходит, если активность умирает на секунду, и только тогда приходит трансляция?ах, это проблема, поэтому Android вводит Sticky Broadcasts, которые остаются там, пока вы не удалите их с помощью removeStickyBroadcast (Intent), поэтому, когда идет трансляция из моего сервиса, я отправляю Sticky трансляцию, когда Activity получает мою трансляцию, она удаляет ее, поэтому она не остаетсявокруг и ввести в заблуждение деятельность о новом ответе, который прибыл.Единственная проблема - если я отправлю запрос, не дождусь ответа и сразу же перейду к следующему действию, в этом случае, когда я вернусь к этому действию, он будет думать, что получил ответ.Пока не нашел правильного решения.Но это лучше, чем мое предыдущее решение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...