Андроид активити
От: Mishka Норвегия  
Дата: 26.10.15 15:02
Оценка:
Пытаю андройд. У меня опыт большой в винде и вёбе, но это совсем новая штука. Объясните пожалуйста, кто знает, почему ж так всё сложно и как с этим бороться? Берём, например, активити, которая бежит на сервер, считывает что-то и отображает. Если читать документацию, то там всё просто — внутренний AsyncTask в активити и усё. Только это во-первых не работает (юзер экран повернёт = краш) и во-вторых вообще memory leak. Разбираемся дальше по ивентам активити и там вообще не понятно, какие из них гарантированы, а какие нет. onDestroy работает не всегда, onStop как оказалось тоже (юзер нажал кнопку Home/Back или выключил девайс). То есть не понятно как за этим всем следить и 90% советов на stackoverflow на самом деле багованые. В итоге я нафиг всё вынес из этих activity, оставив только onResume, но гложут сомнения, что ну не может же быть так всё сложно. Или всё таки может?
Интересен вот такой тест сценарий — юзер запустил активити, запрос ушёл на сервер — 10 секунд задержка например, за это время юзер повернул экран, нажал Home, снова запустил приложение (оно висит в бакграунде). Когда оно запустилось данные уже пришли с сервера и их надо отобразить. Далее юзер нажимает Back — приложение сворачивается. Запускаем по-новой, экран с данными с сервера должен появится. Или я всё ж таки слишком жёстко свою аппу ломаю?
Re: Андроид активити
От: mr_trwister  
Дата: 26.10.15 16:43
Оценка: 12 (1)
http://habrahabr.ru/post/144275/
Re[2]: Андроид активити
От: Mishka Норвегия  
Дата: 26.10.15 19:55
Оценка:
Здравствуйте, mr_trwister, Вы писали:

_>http://habrahabr.ru/post/144275/


Это была попытка номер 2 у меня, пока я не осознал, что onPause не всегда вызывается и соответсвенно просто так нельзя уведомить сервис, что сейчас активити откинет копыта. Отсюда и проблемы с последующим восстановлением после того как юзвер нажал Home.
В общем, пока что вариант с единствнным методом onResume работает, геморойно, но хоть не падает.
Re[3]: Андроид активити
От: mr_trwister  
Дата: 27.10.15 13:11
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, mr_trwister, Вы писали:


_>>http://habrahabr.ru/post/144275/


M>Это была попытка номер 2 у меня, пока я не осознал, что onPause не всегда вызывается и соответсвенно просто так нельзя уведомить сервис, что сейчас активити откинет копыта. Отсюда и проблемы с последующим восстановлением после того как юзвер нажал Home.

M>В общем, пока что вариант с единствнным методом onResume работает, геморойно, но хоть не падает.


насчет того, что onStop может не вызываться — это какое-то сомнительное утверждение в документации.
есть какое-то противоречие в двух независимых цитатах.

Note that this method may never be called, in low memory situations where the system does not have enough memory to keep your activity's process running after its onPause() method is called.


Когда операция получает вызов метода onStop(), она становится невидимой и освобождает практически все ресурсы, которые не нужны ей, когда пользователь ее не использует. После остановки операции система может уничтожить экземпляр, если ей потребуется освободить системную память. В чрезвычайных ситуациях система может закрыть процесс приложения без вызова последнего метода обратного вызова onDestroy() операции, и поэтому важно использовать onStop() для высвобождения ресурсов, которые могут вызвать утечку памяти.

Хотя метод onPause() вызывается до onStop(), вам следует использовать onStop() для выполнения более масштабных операций выключения с использованием процессорных ресурсов, например при записи информации в базу данных.


если это все так супер критично и не требуется отображение обновления после onPause, то можно отключать подписку на события о новых данных в onPause. если нет, то мне кажется можно и в onStop и особо не бояться, пока не появятся факты, что что-то все таки падает
Re: Андроид активити
От: lpd Черногория  
Дата: 27.10.15 13:31
Оценка:
Насчет onStop и прочих, в документации андроид есть Activity lifecycle — он все объясняет.
Для работы с сетью лучше использовать отдельный сервис, обменивающийся с основным активити сообщениями. В ряде случаев Android может прибить основной активити(для экономии памяти, например) а потом перезапустить, при этом сервис может остаться выполняться в бэкграунде. Т.е. если сеть нужна не один раз, а в течение работы приложения, однозначно нужно делать через сервис.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Отредактировано 27.10.2015 13:32 lpd . Предыдущая версия .
Re[2]: Андроид активити
От: mr_trwister  
Дата: 27.10.15 14:36
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>Насчет onStop и прочих, в документации андроид есть Activity lifecycle — он все объясняет.


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

для чего тогда вообще нужны onStop и onDestroy, если система может прибить активити не вызывая их. давайте уже все в onPause пихать ))))))))))
Re[3]: Андроид активити
От: lpd Черногория  
Дата: 27.10.15 14:44
Оценка:
Здравствуйте, mr_trwister, Вы писали:

_>Здравствуйте, lpd, Вы писали:


lpd>>Насчет onStop и прочих, в документации андроид есть Activity lifecycle — он все объясняет.


_>насчет onStop документация как раз не объясняет, а путает. в одном месте написано, что onStop может никогда не быть вызван, а в другом написано, что сохранение в базу данных надо делать в onStop


Не уверен, что у ТС приложение убивается именно из-за нехватки памяти. Оно еще может убиваться при локе устройства и даже повороте экрана, если это не отключено в манифесте активити. То есть достаточно просто настроить activity.xml.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Отредактировано 27.10.2015 14:45 lpd . Предыдущая версия .
Re[2]: Андроид активити
От: Mishka Норвегия  
Дата: 27.10.15 14:54
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>Насчет onStop и прочих, в документации андроид есть Activity lifecycle — он все объясняет.

lpd>Для работы с сетью лучше использовать отдельный сервис, обменивающийся с основным активити сообщениями. В ряде случаев Android может прибить основной активити(для экономии памяти, например) а потом перезапустить, при этом сервис может остаться выполняться в бэкграунде. Т.е. если сеть нужна не один раз, а в течение работы приложения, однозначно нужно делать через сервис.

То, что написано в документации и то, что происходит на самом деле — 2 большие разницы. Вызывается onStart->onResume, жмёшь power off, ни onPause, ни onStop, ни onDestroy. Включаешь девайс, запускаешь прогу — по логам идёт onStart, onResume и тут же onDestroy (видимо на прошлой). Это самсунг телфон 2-ух летней давности.
Re[3]: Андроид активити
От: lpd Черногория  
Дата: 27.10.15 15:09
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, lpd, Вы писали:


lpd>>Насчет onStop и прочих, в документации андроид есть Activity lifecycle — он все объясняет.

lpd>>Для работы с сетью лучше использовать отдельный сервис, обменивающийся с основным активити сообщениями. В ряде случаев Android может прибить основной активити(для экономии памяти, например) а потом перезапустить, при этом сервис может остаться выполняться в бэкграунде. Т.е. если сеть нужна не один раз, а в течение работы приложения, однозначно нужно делать через сервис.

M>То, что написано в документации и то, что происходит на самом деле — 2 большие разницы. Вызывается onStart->onResume, жмёшь power off, ни onPause, ни onStop, ни onDestroy. Включаешь девайс, запускаешь прогу — по логам идёт onStart, onResume и тут же onDestroy (видимо на прошлой). Это самсунг телфон 2-ух летней давности.


Можно в дебаггере Android Studio посмотреть откуда приходит onDestroy и почему — дебаггер показывает исходник андроида. Также можно погуглить call-stack файлы и номера строк — возможно, что кто-то с подобным поведением уже сталкивался. Вообщем-то, onDestroy может по разным причинам приходить. Помню, что у меня были подобные проблемы, но они были связаны с моими ошибками и непониманием API.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Отредактировано 27.10.2015 15:10 lpd . Предыдущая версия .
Re[3]: Андроид активити
От: lpd Черногория  
Дата: 27.10.15 15:31
Оценка: 6 (1)
Здравствуйте, Mishka, Вы писали:

M>То, что написано в документации и то, что происходит на самом деле — 2 большие разницы. Вызывается onStart->onResume, жмёшь power off, ни onPause, ни onStop, ни onDestroy. Включаешь девайс, запускаешь прогу — по логам идёт onStart, onResume и тут же onDestroy (видимо на прошлой). Это самсунг телфон 2-ух летней давности.


Не сразу понял проблему. Если под "выключаешь девайс" подразумевается лочишь, то это нормальное поведение. Чтобы activity обрабатывало это событие самостоятельно, нужно в AndroidManifest.xml добавить в <activity ...>:
android:configChanges="orientation|keyboard|keyboardHidden|screenSize"

Согласен, что поведение android по умолчанию несколько неожиданно.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[4]: Андроид активити
От: Mishka Норвегия  
Дата: 27.10.15 20:40
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>android:configChanges="orientation|keyboard|keyboardHidden|screenSize"


http://developer.android.com/guide/topics/manifest/activity-element.html

Note: Using this attribute should be avoided and used only as a last resort. Please read Handling Runtime Changes for more information about how to properly handle a restart due to a configuration change.

Мне от таких примечаний становится не по себе. В итоге, не верю я в светлое будущее. onResume вроде есть всегда и его хватает пока, буду дальше пилить.
Re[5]: Андроид активити
От: lpd Черногория  
Дата: 27.10.15 20:59
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, lpd, Вы писали:


lpd>>android:configChanges="orientation|keyboard|keyboardHidden|screenSize"


M>http://developer.android.com/guide/topics/manifest/activity-element.html


M>Note: Using this attribute should be avoided and used only as a last resort. Please read Handling Runtime Changes for more information about how to properly handle a restart due to a configuration change.


M>Мне от таких примечаний становится не по себе. В итоге, не верю я в светлое будущее. onResume вроде есть всегда и его хватает пока, буду дальше пилить.


Проблема в том, что при локе экрана расположение поворачивается в landscape, поэтому нужен configChanges="screenSize". Сам не понял, зачем Google пошло на такое усложение, чтобы в этом случае прибивать активити. При событии поворота определенный смысл в этом может быть, хотя мне это мешало, но при обычном локе экрана — .
По своему опыту, к Android тяжело привыкнуть, но все же это возможно, в отличие от iOS.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[3]: Андроид активити
От: mr_trwister  
Дата: 29.10.15 12:12
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, lpd, Вы писали:


lpd>>Насчет onStop и прочих, в документации андроид есть Activity lifecycle — он все объясняет.

lpd>>Для работы с сетью лучше использовать отдельный сервис, обменивающийся с основным активити сообщениями. В ряде случаев Android может прибить основной активити(для экономии памяти, например) а потом перезапустить, при этом сервис может остаться выполняться в бэкграунде. Т.е. если сеть нужна не один раз, а в течение работы приложения, однозначно нужно делать через сервис.

M>То, что написано в документации и то, что происходит на самом деле — 2 большие разницы. Вызывается onStart->onResume, жмёшь power off, ни onPause, ни onStop, ни onDestroy. Включаешь девайс, запускаешь прогу — по логам идёт onStart, onResume и тут же onDestroy (видимо на прошлой). Это самсунг телфон 2-ух летней давности.



это какой андроид? 2.х?
Re[4]: Андроид активити
От: Mishka Норвегия  
Дата: 29.10.15 12:36
Оценка:
Здравствуйте, mr_trwister, Вы писали:

_>Здравствуйте, Mishka, Вы писали:


M>>Здравствуйте, lpd, Вы писали:


lpd>>>Насчет onStop и прочих, в документации андроид есть Activity lifecycle — он все объясняет.

lpd>>>Для работы с сетью лучше использовать отдельный сервис, обменивающийся с основным активити сообщениями. В ряде случаев Android может прибить основной активити(для экономии памяти, например) а потом перезапустить, при этом сервис может остаться выполняться в бэкграунде. Т.е. если сеть нужна не один раз, а в течение работы приложения, однозначно нужно делать через сервис.

M>>То, что написано в документации и то, что происходит на самом деле — 2 большие разницы. Вызывается onStart->onResume, жмёшь power off, ни onPause, ни onStop, ни onDestroy. Включаешь девайс, запускаешь прогу — по логам идёт onStart, onResume и тут же onDestroy (видимо на прошлой). Это самсунг телфон 2-ух летней давности.


_>это какой андроид? 2.х?


https://en.wikipedia.org/wiki/Samsung_Galaxy_S4 — то что с завода
Re[2]: Андроид активити
От: Mishka Норвегия  
Дата: 29.10.15 13:06
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>Насчет onStop и прочих, в документации андроид есть Activity lifecycle — он все объясняет.

lpd>Для работы с сетью лучше использовать отдельный сервис, обменивающийся с основным активити сообщениями. В ряде случаев Android может прибить основной активити(для экономии памяти, например) а потом перезапустить, при этом сервис может остаться выполняться в бэкграунде. Т.е. если сеть нужна не один раз, а в течение работы приложения, однозначно нужно делать через сервис.

А вот эти сервисы — это вообще не в тему. Во-первых, они живут на главном потоке, так что если нужно идти на сервер — всё равно придётся использовать что-то вроде AsyncTask. Далее, система в своей великой мудрости может сервис этот прибить, тот же AsyncTask скорее всего более живуч. И вообще, назначение сервиса — это чтоб другие проги могли его запускать.
Re[3]: Андроид активити
От: lpd Черногория  
Дата: 29.10.15 15:32
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, lpd, Вы писали:


lpd>>Насчет onStop и прочих, в документации андроид есть Activity lifecycle — он все объясняет.

lpd>>Для работы с сетью лучше использовать отдельный сервис, обменивающийся с основным активити сообщениями. В ряде случаев Android может прибить основной активити(для экономии памяти, например) а потом перезапустить, при этом сервис может остаться выполняться в бэкграунде. Т.е. если сеть нужна не один раз, а в течение работы приложения, однозначно нужно делать через сервис.

M>А вот эти сервисы — это вообще не в тему. Во-первых, они живут на главном потоке, так что если нужно идти на сервер — всё равно придётся использовать что-то вроде AsyncTask. Далее, система в своей великой мудрости может сервис этот прибить, тот же AsyncTask скорее всего более живуч. И вообще, назначение сервиса — это чтоб другие проги могли его запускать.


В Android как раз сервис в отдельном потоке выполняется. Кроме того, сервису можно поставить флаг, при котором система его убьет только в _самом_ крайнем случае. AsyncTask же она убьет вместе с активити.
Про сервисы говорю точно, т.к. использовал это в своем проекте.
см. http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification)
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Отредактировано 29.10.2015 15:39 lpd . Предыдущая версия . Еще …
Отредактировано 29.10.2015 15:38 lpd . Предыдущая версия .
Re[4]: Андроид активити
От: Mishka Норвегия  
Дата: 29.10.15 16:59
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>В Android как раз сервис в отдельном потоке выполняется. Кроме того, сервису можно поставить флаг, при котором система его убьет только в _самом_ крайнем случае. AsyncTask же она убьет вместе с активити.

lpd>Про сервисы говорю точно, т.к. использовал это в своем проекте.
lpd>см. http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification)

AsyncTask всё же к Activity не имеет никакого отношения. Более того — An AsycTask is only truly gone when it is completed OR the process is killed which may or may not happen after finish is called. Что в общем-то и нужно и полностью соответсвует нормальной модели программирования. Сервисы же под контролем ОС и могут быть прибиты по поводу и без повода. Мне ещё вот этот комент понравился:

Services get killed. Like app gets killed. It is Android philosophy that you can get killed at any time.
You should as other wrote not make the assumption that your backgroundservice runs forever.
But you can use a foreground service to drastically reduce the chance of getting killed/restarted. Note that this forces a notification which is always visible. For example music players, vpn applications and sportstracker use this API.

Так что AsyncTask >> background service.
Re[5]: Андроид активити
От: lpd Черногория  
Дата: 29.10.15 17:04
Оценка:
Здравствуйте, Mishka, Вы писали:
M>Так что AsyncTask >> background service.

По твоей ссылке на so принятый ответ:
The AsyncTask is tied to a UI thread and if the Activity is finished the async task is canceled.

[update] — Hackbod's comment below is correct. It should be noted that AsyncTasks are meant to be short lived and as such not worry so much about this issue. An AsycTask is only truly gone when it is completed OR the process is killed which may or may not happen after finish is called.
Коммент, на который ты ссылаешься, неправильный, как примерно 40% на so. Дело не в смерти активити, а в том, что может убиться все, кроме foreground service.
См. "жизненный цикл процесса — иерархия важности" в http://developer.android.com/intl/ru/guide/components/processes-and-threads.html

На странице моей ссылки(документация Android):
A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Отредактировано 29.10.2015 17:11 lpd . Предыдущая версия . Еще …
Отредактировано 29.10.2015 17:09 lpd . Предыдущая версия .
Отредактировано 29.10.2015 17:07 lpd . Предыдущая версия .
Re[6]: Андроид активити
От: Mishka Норвегия  
Дата: 29.10.15 19:05
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>Здравствуйте, Mishka, Вы писали:

M>>Так что AsyncTask >> background service.

lpd>По твоей ссылке на so принятый ответ:

lpd>The AsyncTask is tied to a UI thread and if the Activity is finished the async task is canceled.

Я точно 100% вижу, что мой AsyncTask живёт после того как активити убита. Более того, он живёт даже когда этих активити нет и апп просто висит в бакграунде. Точно тебе говорю, единственный вариант убить AsyncTask — это убить апп, а это убивает любой сервис.
Re[7]: Андроид активити
От: lpd Черногория  
Дата: 30.10.15 07:54
Оценка:
Здравствуйте, Mishka, Вы писали:

M>Здравствуйте, lpd, Вы писали:


lpd>>Здравствуйте, Mishka, Вы писали:

M>>>Так что AsyncTask >> background service.

lpd>>По твоей ссылке на so принятый ответ:

lpd>>The AsyncTask is tied to a UI thread and if the Activity is finished the async task is canceled.

M>Я точно 100% вижу, что мой AsyncTask живёт после того как активити убита. Более того, он живёт даже когда этих активити нет и апп просто висит в бакграунде. Точно тебе говорю, единственный вариант убить AsyncTask — это убить апп, а это убивает любой сервис.


Дело не в смерти одной активити. В Android специальный механизм освобождения памяти. Почитай про иерархию потоков по моей ссылке — AsyncTask убьется при освобождении памяти, иного поведения не задано; AsyncTask это просто небольшой удобный инструмент, чтобы не создавать громоздким кодом потоки. А foregroundService у меня оставалось работать и обрабатывать сеть после того, как система при нехватке памяти убивала активити.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Отредактировано 30.10.2015 7:56 lpd . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.