Na maioria dos casos, cada aplicativo para Android é executado no próprio processo do Linux. Esse processo é criado para o aplicativo quando parte do código precisa ser executada e permanece em execução até que o sistema precise recuperar a memória para uso por outros aplicativos e ela não seja mais necessária.
Um recurso incomum e fundamental do Android é que a vida útil do processo de um app não é controlada diretamente pelo próprio app. Em vez disso, ele é determinado pelo sistema usando uma combinação das partes do app que o sistema sabe que estão em execução, da importância dessas coisas para o usuário e da quantidade de memória geral disponível no sistema.
É importante que
os desenvolvedores de aplicativos entendam como diferentes componentes de aplicativos
(em especial Activity
, Service
e BroadcastReceiver
) afetam o ciclo de vida
do processo do aplicativo. Não usar esses componentes corretamente pode
fazer com que o sistema elimine o processo do app enquanto ele está fazendo
um trabalho importante.
Um exemplo comum de bug de ciclo de vida do processo é um
BroadcastReceiver
que inicia uma linha de execução quando
recebe um Intent
no método BroadcastReceiver.onReceive()
e, em seguida, retorna da função. Depois que ele retorna, o sistema
considera que o BroadcastReceiver
não está mais ativo e o processo de
hospedagem dele não é mais necessário, a menos que outros componentes do aplicativo estejam
ativos.
Assim, o sistema pode encerrar o processo a qualquer momento para liberar memória e, ao fazer isso, ele encerra a linha de execução gerada no processo. Normalmente, a solução para esse problema
é programar um JobService
no BroadcastReceiver
para que o
sistema saiba que há trabalho ativo ocorrendo no processo.
Para determinar quais processos encerrar quando estiver com pouca memória, o Android coloca cada processo em uma hierarquia de importância com base nos componentes em execução e no estado deles. Em ordem de importância, esses tipos de processo são:
- Um processo em primeiro plano é necessário para
o que o usuário está fazendo no momento. Vários componentes de aplicativo podem
fazer com que o processo que o contém seja considerado em primeiro plano de diferentes
maneiras. Um processo é considerado em primeiro plano se alguma das
seguintes condições ocorrer:
- Ele está executando um
Activity
na parte de cima da tela com que o usuário está interagindo (o métodoonResume()
foi chamado). - Ele tem um
BroadcastReceiver
que está em execução no momento (o métodoBroadcastReceiver.onReceive()
está em execução). - Ela tem um
Service
que está executando o código em um dos callbacks (Service.onCreate()
,Service.onStart()
ouService.onDestroy()
).
- Ele está executando um
- Um processo visível está realizando uma tarefa da qual o usuário está ciente no momento.
Portanto, encerrá-lo tem um impacto negativo perceptível na experiência do usuário. Um processo é
considerado visível nas seguintes condições:
- Ele está executando um
Activity
visível para o usuário na tela, mas não em primeiro plano (o métodoonPause()
foi chamado). Isso pode ocorrer, por exemplo, se aActivity
em primeiro plano for exibida como uma caixa de diálogo que permite que oActivity
anterior seja visto por trás dele. - Ele tem um
Service
que está sendo executado como um serviço em primeiro plano, por meio deService.startForeground()
, que pede ao sistema para tratar o serviço como algo de que o usuário está ciente ou essencialmente como se ele estivesse visível. - Ele hospeda um serviço que o sistema usa para um recurso específico de que o usuário está ciente, como um plano de fundo interativo ou um serviço de método de entrada.
O número desses processos em execução no sistema é menos limitado que os processos em primeiro plano, mas ainda relativamente controlado. Esses processos são considerados extremamente importantes e não são encerrados, a menos que isso seja necessário para manter todos os processos em primeiro plano em execução.
- Ele está executando um
- Um processo de serviço é aquele que contém um
Service
que foi iniciado com o métodostartService()
. Embora esses processos não estejam diretamente visíveis para o usuário, eles geralmente realizam coisas importantes para o usuário (como upload ou download de dados de rede em segundo plano). Assim, o sistema sempre mantém esses processos em execução, a menos que não haja memória suficiente para reter todos os processos visíveis e em primeiro plano.Os serviços que estão em execução há muito tempo (como 30 minutos ou mais) podem ser rebaixados para permitir que o processo seja adicionado à lista em cache.
Os processos que precisam ser executados por um período longo podem ser criados com
setForeground
. Se for um processo periódico que exige um tempo de execução rigoroso, ele pode ser programado usando oAlarmManager
. Para mais informações, consulte Suporte para workers de longa duração. Isso ajuda a evitar situações em que serviços de longa duração que usam recursos em excesso, por exemplo, devido a vazamento de memória, impedem o sistema de oferecer uma boa experiência ao usuário. - Um processo armazenado em cache é um que não é necessário no momento. Portanto, o
sistema fica livre para eliminá-lo conforme necessário quando recursos como a memória forem necessários em outro lugar. Em um sistema
com comportamento normal, esses são os únicos processos envolvidos no gerenciamento de recursos.
Um sistema bem executado tem vários processos em cache sempre disponíveis para alternar entre aplicativos com eficiência e elimina regularmente os apps armazenados em cache conforme necessário. Somente em situações muito críticas o sistema chega a um ponto em que todos os processos armazenados em cache são encerrados e precisa começar a encerrar processos de serviço.
Como os processos armazenados em cache podem ser encerrados pelo sistema a qualquer momento, os apps precisam interromper todo o trabalho enquanto estiverem no estado armazenado em cache. Se o trabalho essencial para o usuário precisar ser realizado pelo app, ele precisará usar as APIs acima para executar o trabalho em um estado de processo ativo.
Os processos armazenados em cache geralmente contêm uma ou mais instâncias de
Activity
que não estão visíveis no momento para o usuário. O métodoonStop()
deles foi chamado e retornou. Desde que o ciclo de vidaActivity
seja implementado corretamente quando o sistema encerra esses processos, isso não afeta a experiência do usuário ao retornar ao app. Ele pode restaurar o estado salvo anteriormente quando a atividade associada é recriada em um novo processo. Esteja ciente de que não há garantia de queonDestroy()
será chamado caso um processo seja encerrado pelo sistema. Confira mais detalhes emActivity
.No Android 13 e versões mais recentes, o processo do app pode ter tempo de execução limitado ou nenhum tempo de execução até entrar em um dos estados ativos do ciclo de vida acima.
Os processos armazenados em cache são mantidos em uma lista. A política exata de pedidos para essa lista é um detalhe de implementação da plataforma. Geralmente, ela tenta manter processos mais úteis, por exemplo, aqueles que hospedam o aplicativo inicial do usuário ou a última atividade que o usuário viu, antes de outros tipos de processos. Outras políticas para encerrar processos também podem ser aplicadas, como a definição de limites rígidos no número de processos permitidos ou a limitação do tempo que um processo pode permanecer continuamente armazenado em cache.
Existem apenas alguns desses processos no sistema, e eles só são eliminados como último recurso se a memória estiver tão baixa que nem mesmo esses processos puderem continuar em execução. Geralmente, se isso acontecer, o dispositivo terá alcançado um estado de paginação de memória. Portanto, essa ação é necessária para manter a interface do usuário responsiva.
Ao decidir como classificar um processo, o sistema baseia a decisão no nível mais
importante encontrado entre todos os componentes ativos no processo.
Consulte a documentação Activity
, Service
e
BroadcastReceiver
para ver mais detalhes sobre como
cada um desses componentes contribui para o ciclo de vida geral de um processo e
do aplicativo.
A prioridade de um processo também pode ser aumentada com base em outras dependências
de um processo em relação a ele. Por exemplo, se o processo A estiver vinculado a um Service
com a sinalização Context.BIND_AUTO_CREATE
ou estiver usando um ContentProvider
no processo B, a classificação do processo B será sempre pelo menos tão importante quanto a do A.