Na maioria dos casos, cada aplicativo para Android é executado no próprio processo do Linux. Esse processo é criado para o app quando parte do código precisa ser executada e permanece em execução até que o sistema precise reivindicar a memória para uso por outros apps e não seja mais necessário.
Uma característica incomum e fundamental do Android é que o ciclo de vida do processo de um app não é diretamente controlado pelo próprio app. Em vez disso, ele é determinado pelo sistema por meio de uma combinação das partes do aplicativo que o sistema sabe que estão sendo executadas, da importância delas para o usuário e da quantidade de memória disponível no sistema.
É importante que
os desenvolvedores de apps entendam como componentes de aplicativo diferentes
(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 estiver fazendo
um trabalho importante.
Um exemplo comum de um bug do ciclo de vida do processo é um
BroadcastReceiver
que inicia uma linha de execução quando
recebe um Intent
no método BroadcastReceiver.onReceive()
e retorna da função. Depois que ele retorna, o sistema
considera que o BroadcastReceiver
não está mais ativo e que o processo de hospedagem
dele não é mais necessário, a menos que outros componentes do aplicativo estejam ativos
nele.
Assim, o sistema pode eliminar o processo a qualquer momento para recuperar a memória e, ao fazer isso,
encerrar a linha de execução gerada no processo. A solução para esse problema
é normalmente programar um JobService
a partir do BroadcastReceiver
para que o
sistema saiba que há trabalho ativo no processo.
Para determinar quais processos precisam ser eliminados quando a memória estiver baixa, o Android coloca cada processo em uma hierarquia de importância com base nos componentes executados neles e no estado desses componentes. Em ordem de importância, esses tipos de processo são:
- Um processo em primeiro plano é aquele que é 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 maneiras
diferentes. Um processo é considerado em primeiro plano se atender a alguma das
seguintes condições:
- Ele está executando um
Activity
na parte de cima da tela com a qual o usuário está interagindo. O métodoonResume()
foi chamado. - Ele tem um
BroadcastReceiver
que está sendo executado (o métodoBroadcastReceiver.onReceive()
está em execução). - Ele 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.
Por isso, encerrá-lo causa um impacto negativo significativo 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 aActivity
anterior seja vista por trás dela. - Ele tem um
Service
em execução como um serviço em primeiro plano, por meio deService.startForeground()
, que pede ao sistema para tratar o serviço como algo que o usuário conhece ou, essencialmente, como se estivesse visível. - Ele hospeda um serviço que o sistema está usando para um recurso específico do qual 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 eliminados, 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 sejam diretamente visíveis para o usuário, eles geralmente fazem coisas que são importantes para o usuário (como upload ou download de dados de rede em segundo plano). Portanto, o sistema sempre mantém esses processos em execução, a menos que não haja memória suficiente para reter todos os processos em primeiro plano e visíveis.Os serviços que estão em execução há muito tempo, como 30 minutos ou mais, podem ter a importância rebaixada para permitir que o processo seja enviado para a lista de LRUs em cache.
Os processos que precisam ser executados por um longo período podem ser criados com
setForeground
. Se for um processo periódico que exige um tempo de execução rígido, ele poderá ser programado peloAlarmManager
. 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 excessivos, por exemplo, com vazamento de memória, impedem que o sistema ofereça uma boa experiência do usuário. - Um processo armazenado em cache é um que não é necessário no momento. Portanto, o
sistema está livre para eliminá-lo conforme necessário quando recursos como 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 apps de modo eficiente, e elimina com frequência os mais antigos, conforme necessário. Somente em situações muito críticas, o sistema chega a um ponto em que todos os processos em cache são eliminados e ele precisa começar a eliminar processos de serviço.
Como os processos em cache podem ser encerrados pelo sistema a qualquer momento, os apps precisam interromper todo o trabalho enquanto estiverem no estado de cache. Se o app precisar realizar um trabalho crítico para o usuário, ele precisará usar uma das APIs acima para executar o trabalho em um estado de processo ativo.
Os processos em cache geralmente contêm uma ou mais instâncias
Activity
que não estão visíveis no momento para o usuário. O métodoonStop()
foi chamado e retornado. Contanto que o ciclo de vidaActivity
seja implementado corretamente quando o sistema encerrar esses processos, ele não vai afetar 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. Não há garantia de queonDestroy()
será chamado no caso de um processo ser encerrado pelo sistema. Para mais detalhes, consulteActivity
.A partir do Android 13, um processo de app pode receber tempo de execução limitado ou nenhum até entrar em um dos estados ativos do ciclo de vida acima.
Os processos em cache são mantidos em uma lista. A política de ordenação exata para essa lista é um detalhe de implementação da plataforma. Geralmente, ele tenta manter processos mais úteis, como aqueles que hospedam o app de início do usuário ou a última atividade que ele acessou, antes de outros tipos de processos. Outras políticas para eliminar processos também podem ser aplicadas, como definir limites rígidos no número de processos permitidos ou limitar o tempo que um processo pode permanecer continuamente armazenado em cache.
Só haverá alguns desses processos no sistema, e eles só serão eliminados como um último recurso se a memória estiver tão baixa que nem mesmo esses processos possam 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 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 outro processo a ele. Por exemplo, se o processo A estiver vinculado a um
Service
com
a flag 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 processo A.