En la mayoría de los casos, cada aplicación para Android ejecuta su propio proceso de Linux. Este proceso se crea para la aplicación cuando es necesario ejecutar parte de su código, y seguirá ejecutándose hasta que el sistema necesite recuperar su memoria para que la usen otras aplicaciones y ya no sea necesario.
Una característica poco común y fundamental de Android es que la duración del proceso de una aplicación no se controla directamente desde la aplicación. En su lugar, el sistema la determina mediante una combinación de las partes de la aplicación que el sistema sabe que se están ejecutando, la importancia de estas para el usuario y la cantidad total de memoria disponible en el sistema.
Es importante que los desarrolladores de aplicaciones comprendan cómo los diferentes componentes de la aplicación (en especial Activity
, Service
y BroadcastReceiver
) afectan la duración del proceso de la aplicación. Si estos componentes no se usan correctamente, el sistema puede eliminar el proceso de la aplicación mientras realiza una tarea importante.
Un ejemplo común de un error del ciclo de vida del proceso es un BroadcastReceiver
que inicia un subproceso cuando recibe un Intent
en su método BroadcastReceiver.onReceive()
y, luego, regresa de la función. Una vez que regresa, el sistema considera que el BroadcastReceiver
ya no está activo y que su proceso de hosting ya no es necesario, a menos que otros componentes de la aplicación estén activos en él.
Por lo tanto, el sistema puede eliminar el proceso en cualquier momento para recuperar memoria y, al hacerlo, finaliza el subproceso generado que se está ejecutando en el proceso. Una solución común a este problema es programar un JobService
desde el BroadcastReceiver
para que el sistema sepa que hay trabajo activo en el proceso.
Para determinar qué procesos finalizar cuando hay poca memoria, Android coloca cada proceso en una jerarquía de importancia basada en los componentes que se ejecutan en ellos y el estado de esos componentes. En orden de importancia, estos son los tipos de procesos:
- Un proceso en primer plano es uno que se requiere para lo que el usuario está haciendo actualmente. Varios componentes de la aplicación pueden hacer que el proceso que los contiene se considere en primer plano de diferentes maneras. Un proceso se considera en primer plano si se cumple alguna de las siguientes condiciones:
- Ejecuta una
Activity
en la parte superior de la pantalla con la que el usuario está interactuando (se llamó a su métodoonResume()
). - Tiene un
BroadcastReceiver
que actualmente está en ejecución (se está ejecutando su métodoBroadcastReceiver.onReceive()
). - Tiene un
Service
que actualmente está ejecutando código en una de sus devoluciones de llamadas (Service.onCreate()
,Service.onStart()
oService.onDestroy()
).
- Ejecuta una
- Un proceso visible realiza una tarea sobre la que el usuario tiene conocimiento, por lo que su eliminación tiene un impacto negativo notable en la experiencia del usuario. Un proceso se considera visible en las siguientes condiciones:
- Ejecuta una
Activity
que es visible para el usuario en pantalla, pero no en primer plano (se llamó a su métodoonPause()
). Esto puede ocurrir, por ejemplo, si elActivity
en primer plano se muestra como un diálogo que permite ver elActivity
anterior detrás de él. - Tiene un
Service
que se ejecuta como servicio en primer plano por medio deService.startForeground()
(que le pide al sistema que trate el servicio como algo que el usuario conoce o que es esencialmente visible para este). - Aloja un servicio que el sistema usa para una función que el usuario conoce, como un fondo animado o un servicio de método de entrada.
La cantidad de procesos que se ejecutan en el sistema es menos limitada que los procesos en primer plano, pero aún está relativamente controlada. Estos procesos se consideran sumamente importantes y no se eliminan a menos que sea necesario para mantener en ejecución todos los procesos en primer plano.
- Ejecuta una
- Un proceso de servicio es aquel que contiene un
Service
que se inició con el métodostartService()
. Aunque el usuario no puede ver estos procesos directamente, por lo general, realizan acciones que le interesan (como la carga o descarga de datos de red en segundo plano), por lo que el sistema siempre mantiene estos procesos en ejecución, a menos que no haya suficiente memoria para retener todos los procesos en primer plano y visibles.Es posible que se descienda el nivel de importancia de los servicios que han estado ejecutándose por un tiempo prolongado (como 30 minutos o más) para permitir que sus procesos se incluyan en la lista almacenada en caché.
Los procesos que sí deben ejecutarse durante un período prolongado se pueden crear con
setForeground
. Si se trata de un proceso periódico que requiere un tiempo de ejecución estricto, se puede programar a través deAlarmManager
. Para obtener más información, consulta Compatibilidad con trabajadores de larga duración. De esta manera, se evitan situaciones en las que los servicios de larga duración que usan recursos excesivos, por ejemplo, a través de pérdidas de memoria, impiden que el sistema proporcione una buena experiencia del usuario. - Un proceso almacenado en caché es uno que no se necesita actualmente, por lo que el sistema puede eliminarlo cuando lo desee si se necesitan recursos como la memoria en otra parte. En un sistema con comportamiento normal, estos son los únicos procesos involucrados en la administración de recursos.
Un sistema que funciona bien tiene varios procesos almacenados en caché siempre disponibles, para que la alternancia entre aplicaciones sea eficiente, y finaliza las apps almacenadas en caché con regularidad según sea necesario. Solo en situaciones muy críticas el sistema llega a un punto en el que todos los procesos almacenados en caché se eliminan y debe comenzar a eliminar los procesos del servicio.
Dado que el sistema puede finalizar los procesos almacenados en caché en cualquier momento, las apps deben dejar de funcionar mientras se encuentran en ese estado. Si la app debe realizar un trabajo fundamental para el usuario, debe usar una de las APIs anteriores para ejecutar el trabajo desde un estado de proceso activo.
Los procesos almacenados en caché suelen contener una o más instancias de una
Activity
que el usuario no puede ver en este momento (se llamó y se mostró su métodoonStop()
). Siempre que implementen su ciclo de vida deActivity
correctamente cuando el sistema mate esos procesos, no afectará la experiencia del usuario cuando vuelva a esa app. Puede restablecer el estado guardado anteriormente cuando la actividad asociada se vuelva a crear en un proceso nuevo. Ten en cuenta que no se garantiza que se llame aonDestroy()
en el caso de que el sistema cierre un proceso. Para obtener más información, consultaActivity
.A partir de Android 13, un proceso de la app puede recibir un tiempo de ejecución limitado o no hasta que ingrese a uno de los estados de ciclo de vida activo anteriores.
Los procesos almacenados en caché se mantienen en una lista. La política de orden exacta de esta lista es un detalle de implementación de la plataforma. Por lo general, intenta mantener los procesos más útiles, como los que alojan la aplicación principal del usuario o la última actividad que vio, antes de otros tipos de procesos. También se pueden aplicar otras políticas para eliminar procesos, como establecer límites más restrictivos en la cantidad de procesos permitidos o limitar la cantidad de tiempo que un proceso puede permanecer almacenado en caché de manera continua.
Solo hay unos pocos procesos de este tipo en el sistema, y solo se eliminan como último recurso si la memoria es tan baja que ni siquiera estos pueden continuar ejecutándose. Por lo general, si esto sucede, el dispositivo alcanzó un estado de paginación de memoria, por lo que esta acción es necesaria para que la interfaz de usuario responda.
Cuando se decide cómo clasificar un proceso, el sistema basa su decisión en el nivel más importante que se encuentra entre todos los componentes actualmente activos en el proceso.
Consulta la documentación de Activity
, Service
y BroadcastReceiver
para obtener más detalles sobre cómo cada uno de estos componentes contribuye al ciclo de vida general de un proceso y de la aplicación.
La prioridad de un proceso también puede aumentar en función de otras dependencias que tenga un proceso. Por ejemplo, si el proceso A está vinculado a un Service
con la marca Context.BIND_AUTO_CREATE
o usa un ContentProvider
en el proceso B, la clasificación del proceso B siempre será al menos tan importante como la del proceso A.