Процессы и жизненный цикл приложения,Процессы и жизненный цикл приложения

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

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

Важно, чтобы разработчики приложений понимали, как различные компоненты приложения (в частности, Activity , Service и BroadcastReceiver ) влияют на время жизни процесса приложения. Неправильное использование этих компонентов может привести к тому, что система завершит процесс приложения, пока оно выполняет важную работу.

Типичным примером ошибки жизненного цикла процесса является BroadcastReceiver , который запускает поток, когда он получает Intent в своем методе BroadcastReceiver.onReceive() , а затем возвращается из функции. После его возврата система считает, что BroadcastReceiver больше не активен и его хост-процесс больше не нужен, если в нем не активны другие компоненты приложения.

Таким образом, система может в любой момент завершить процесс, чтобы освободить память, и при этом она завершает порожденный поток, выполняющийся в процессе. Решением этой проблемы обычно является планирование JobService из BroadcastReceiver , чтобы система знала, что в процессе выполняется активная работа.

Чтобы определить, какие процессы следует завершить при нехватке памяти, Android помещает каждый процесс в иерархию важности на основе работающих в них компонентов и состояния этих компонентов. В порядке важности эти типы процессов следующие:

  1. Процесс переднего плана — это процесс, который необходим для того, что в данный момент делает пользователь. Различные компоненты приложения могут по-разному привести к тому, что содержащий его процесс будет считаться приоритетным. Считается, что процесс находится на переднем плане, если выполняется любое из следующих условий:
  2. Таких процессов в системе всего несколько, и они уничтожаются только в крайнем случае, если памяти настолько мало, что даже эти процессы не могут продолжать работать. Обычно, если это происходит, устройство достигло состояния подкачки памяти, поэтому это действие необходимо для поддержания отзывчивости пользовательского интерфейса.

  3. Видимый процесс выполняет работу, о которой пользователь в данный момент знает, поэтому его удаление оказывает заметное негативное влияние на работу пользователя. Процесс считается видимым при следующих условиях:
    • Он запускает Activity , которое видно пользователю на экране, но не на переднем плане (вызывается его метод onPause() ). Это может произойти, например, если Activity на переднем плане отображается в виде диалогового окна, в котором за ним можно увидеть предыдущее Activity .
    • У него есть Service , которая работает как служба переднего плана через Service.startForeground() (которая просит систему рассматривать эту службу как что-то, о чем знает пользователь, или, по сути, как если бы она была видимой).
    • Это хостинг службы, которую система использует для определенной функции, о которой знает пользователь, например, живых обоев или службы метода ввода.

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

  4. Процесс службы — это процесс, содержащий Service , запущенную с помощью метода startService() . Хотя эти процессы не видны пользователю напрямую, они обычно выполняют действия, которые интересуют пользователя (например, фоновую загрузку или выгрузку сетевых данных), поэтому система всегда поддерживает такие процессы запущенными, если только не хватает памяти для сохранения всего переднего плана. и видимые процессы.

    Службы, работающие в течение длительного времени (например, 30 минут и более), могут быть понижены по важности, чтобы позволить их процессам попасть в список кэширования.

    Процессы, которые необходимо запускать в течение длительного периода, можно создать с помощью setForeground . Если это периодический процесс, требующий строгого времени выполнения, его можно запланировать с помощью AlarmManager . Дополнительные сведения см. в разделе Поддержка долго работающих рабочих процессов . Это помогает избежать ситуаций, когда долго работающие службы, использующие чрезмерные ресурсы, например, из-за утечки памяти, не позволяют системе обеспечить удобство работы с пользователем.

  5. Кэшированный процесс — это процесс, который в данный момент не нужен, поэтому система может завершить его по мере необходимости, когда ресурсы, такие как память, потребуются где-то еще. В нормально работающей системе это единственные процессы, участвующие в управлении ресурсами.

    Хорошо работающая система всегда имеет несколько доступных кешированных процессов для эффективного переключения между приложениями и регулярно закрывает кешированные приложения по мере необходимости. Только в очень критических ситуациях система доходит до того, что все кэшированные процессы уничтожаются, и она должна начать убивать служебные процессы.

    Поскольку кешированные процессы могут быть завершены системой в любой момент, приложения должны прекратить всю работу, пока находятся в кешированном состоянии. Если приложение должно выполнять критически важную для пользователя работу, ему следует использовать вышеуказанные API для запуска работы из состояния активного процесса.

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

    Начиная с Android 13, процесс приложения может иметь ограниченное время выполнения или вообще не выполняться, пока не перейдет в одно из указанных выше активных состояний жизненного цикла.

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

Принимая решение о классификации процесса, система основывает свое решение на наиболее важном уровне, обнаруженном среди всех компонентов, активных в данный момент в процессе. Дополнительную информацию о том, как каждый из этих компонентов влияет на общий жизненный цикл процесса и приложения, см. в документации по Activity , Service и BroadcastReceiver

Приоритет процесса также может быть увеличен на основе других зависимостей, которые процесс имеет от него. Например, если процесс A привязан к Service с помощью флага Context.BIND_AUTO_CREATE или использует ContentProvider в процессе B, то классификация процесса B всегда не менее важна, чем классификация процесса A.

,

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

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

Важно, чтобы разработчики приложений понимали, как различные компоненты приложения (в частности, Activity , Service и BroadcastReceiver ) влияют на время жизни процесса приложения. Неправильное использование этих компонентов может привести к тому, что система завершит процесс приложения, пока оно выполняет важную работу.

Типичным примером ошибки жизненного цикла процесса является BroadcastReceiver , который запускает поток, когда он получает Intent в своем методе BroadcastReceiver.onReceive() , а затем возвращается из функции. После его возврата система считает, что BroadcastReceiver больше не активен и его хост-процесс больше не нужен, если в нем не активны другие компоненты приложения.

Таким образом, система может в любой момент завершить процесс, чтобы освободить память, и при этом она завершает порожденный поток, выполняющийся в процессе. Решением этой проблемы обычно является планирование JobService из BroadcastReceiver , чтобы система знала, что в процессе выполняется активная работа.

Чтобы определить, какие процессы следует завершить при нехватке памяти, Android помещает каждый процесс в иерархию важности на основе работающих в них компонентов и состояния этих компонентов. В порядке важности эти типы процессов следующие:

  1. Процесс переднего плана — это процесс, который необходим для того, что в данный момент делает пользователь. Различные компоненты приложения могут по-разному привести к тому, что содержащий его процесс будет считаться приоритетным. Считается, что процесс находится на переднем плане, если выполняется любое из следующих условий:
  2. Таких процессов в системе всего несколько, и они уничтожаются только в крайнем случае, если памяти настолько мало, что даже эти процессы не могут продолжать работать. Обычно, если это происходит, устройство достигло состояния подкачки памяти, поэтому это действие необходимо для поддержания отзывчивости пользовательского интерфейса.

  3. Видимый процесс выполняет работу, о которой пользователь в данный момент знает, поэтому его удаление оказывает заметное негативное влияние на работу пользователя. Процесс считается видимым при следующих условиях:
    • Он запускает Activity , которое видно пользователю на экране, но не на переднем плане (вызывается его метод onPause() ). Это может произойти, например, если Activity на переднем плане отображается в виде диалогового окна, в котором за ним можно увидеть предыдущее Activity .
    • У него есть Service , которая работает как служба переднего плана через Service.startForeground() (которая просит систему рассматривать эту службу как что-то, о чем знает пользователь, или, по сути, как если бы она была видимой).
    • Это хостинг службы, которую система использует для определенной функции, о которой знает пользователь, например, живых обоев или службы метода ввода.

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

  4. Процесс службы — это процесс, содержащий Service , запущенную с помощью метода startService() . Хотя эти процессы не видны пользователю напрямую, они обычно выполняют действия, которые интересуют пользователя (например, фоновую загрузку или выгрузку сетевых данных), поэтому система всегда поддерживает такие процессы запущенными, если только не хватает памяти для сохранения всего переднего плана. и видимые процессы.

    Службы, работающие в течение длительного времени (например, 30 минут и более), могут быть понижены по важности, чтобы позволить их процессам попасть в список кэширования.

    Процессы, которые необходимо запускать в течение длительного периода, можно создать с помощью setForeground . Если это периодический процесс, требующий строгого времени выполнения, его можно запланировать с помощью AlarmManager . Дополнительные сведения см. в разделе Поддержка долго работающих рабочих процессов . Это помогает избежать ситуаций, когда долго работающие службы, использующие чрезмерные ресурсы, например, из-за утечки памяти, не позволяют системе обеспечить удобство работы с пользователем.

  5. Кэшированный процесс — это процесс, который в данный момент не нужен, поэтому система может завершить его по мере необходимости, когда ресурсы, такие как память, потребуются где-то еще. В нормально работающей системе это единственные процессы, участвующие в управлении ресурсами.

    Хорошо работающая система всегда имеет несколько доступных кешированных процессов для эффективного переключения между приложениями и регулярно закрывает кешированные приложения по мере необходимости. Только в очень критических ситуациях система доходит до того, что все кэшированные процессы уничтожаются, и она должна начать убивать служебные процессы.

    Поскольку кешированные процессы могут быть завершены системой в любой момент, приложения должны прекратить всю работу, пока находятся в кешированном состоянии. Если приложение должно выполнять критически важную для пользователя работу, ему следует использовать вышеуказанные API для запуска работы из состояния активного процесса.

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

    Начиная с Android 13, процесс приложения может иметь ограниченное время выполнения или вообще не выполняться, пока не перейдет в одно из указанных выше активных состояний жизненного цикла.

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

Принимая решение о классификации процесса, система основывает свое решение на наиболее важном уровне, обнаруженном среди всех компонентов, активных в данный момент в процессе. Дополнительную информацию о том, как каждый из этих компонентов влияет на общий жизненный цикл процесса и приложения, см. в документации по Activity , Service и BroadcastReceiver

Приоритет процесса также может быть увеличен на основе других зависимостей, которые процесс имеет от него. Например, если процесс A привязан к Service с помощью флага Context.BIND_AUTO_CREATE или использует ContentProvider в процессе B, то классификация процесса B всегда не менее важна, чем классификация процесса A.