À medida que o usuário navega no aplicativo, sai dele e retorna a ele, as instâncias Activity
no aplicativo transitam entre diferentes estados no ciclo de vida.
A classe Activity
fornece vários callbacks
que informam à atividade quando um estado muda ou que o
sistema está criando, interrompendo ou retomando uma atividade ou destruindo
o processo em que a atividade reside.
Dentro dos métodos de callback do ciclo de vida, você pode declarar como a atividade deve se comportar quando o usuário sai e retorna dela. Por exemplo, se você estiver criando um player de vídeo com streaming, poderá pausar o vídeo e encerrar a conexão de rede quando o usuário alterna para outro aplicativo. Quando o usuário retorna, é possível reconectar à rede e permitir que o usuário retome o vídeo na mesmo lugar.
Cada callback permite executar um trabalho específico apropriado a uma determinada mudança de estado. Fazer o trabalho certo no momento apropriado e gerenciar as transições da maneira correta faz com que seu aplicativo seja mais robusto e tenha melhor desempenho. Por exemplo, uma boa implementação dos callbacks do ciclo de vida pode ajudar seu app evite o seguinte:
- Falhas se o usuário receber uma chamada telefônica ou mudar para outro aplicativo enquanto estiver usando seu aplicativo.
- Consumo de recursos importantes do sistema quando o usuário não estiver usando ativamente o aplicativo.
- Perda do progresso do usuário se ele sair do aplicativo e retornar mais tarde.
- Falhas ou perda do progresso do usuário quando a orientação da tela mudar entre paisagem e retrato.
Este documento explica detalhadamente o ciclo de vida da atividade. O documento começa descrevendo o paradigma do ciclo de vida. A seguir, ele explica cada um dos callbacks: o que acontece internamente durante a execução e o que você precisa implementar durante o processo.
Depois é apresentada a relação entre o estado da atividade e a vulnerabilidade de um processo que está sendo eliminado pelo sistema. Por fim, ele discute vários tópicos relacionados às transições entre estados de atividade.
Para mais informações sobre como lidar com ciclos de vida, incluindo orientações sobre práticas recomendadas, consulte Como gerenciar ciclos de vida com componentes que os reconhecem e Salvar estados da interface. Para aprender a arquitetar um app robusto e com qualidade de produção usando atividades com os componentes da arquitetura, consulte Guia para a arquitetura do app.
Conceitos do ciclo de vida da atividade
Para navegar pelas transições entre os estágios do ciclo de vida da atividade, o
A classe Activity
fornece um conjunto principal de seis callbacks:
onCreate()
,
onStart()
,
onResume()
,
onPause()
,
onStop()
e
onDestroy()
. O sistema invoca
cada um desses callbacks à medida que a atividade entra em um novo estado.
A imagem 1 demonstra a representação visual desse paradigma.
À medida que o usuário começa a sair da atividade, o sistema chama métodos para eliminá-la. Em alguns casos, a atividade é apenas parcialmente desmontadas e ainda residem na memória, como quando o usuário muda outro app. Nesses casos, a atividade ainda pode voltar para o primeiro plano.
Se o usuário retornar à atividade, é retomado de onde o usuário parou. Com algumas exceções, restrito a partir de iniciar atividades durante a execução em segundo plano.
A probabilidade de o sistema eliminar um determinado processo, juntamente com as atividades nele, depende do estado da atividade no momento. Para mais informações sobre a relação entre estado e vulnerabilidade para expulsão, consulte a seção sobre estado da atividade e expulsão da memória.
Dependendo da complexidade de sua atividade, não é necessário implementar todos os métodos do ciclo de vida. No entanto, é importante que você entender cada um e implementar aqueles que fazem seu aplicativo se comportar do jeito que os usuários esperam.
Callbacks do ciclo de vida
Esta seção fornece informações conceituais e de implementação sobre os métodos de callback usados durante o ciclo de vida da atividade.
Algumas ações pertencem aos métodos do ciclo de vida da atividade. No entanto, o código de lugar que implementa as ações de um componente dependente na em vez do método do ciclo de vida da atividade. Para fazer isso, você precisa para que o componente dependente reconheça o ciclo de vida. Para aprender a fazer os componentes dependentes com reconhecimento de ciclo de vida, consulte Como gerenciar ciclos de vida com componentes que os reconhecem.
onCreate()
Esse callback precisa ser implementado. Ele é acionado assim que o sistema cria a atividade. Quando a atividade é criada, ela insere o estado Criado.
No onCreate()
, execute a lógica básica de inicialização do aplicativo que
acontece apenas uma vez durante toda a vida da atividade.
Por exemplo, seu
implementação de onCreate()
pode vincular dados a listas, associar a atividade a um
ViewModel
,
e instanciar algumas variáveis com escopo de classe. Esse método recebe o evento
parâmetro savedInstanceState
, que é um Bundle
que contém o estado anteriormente salvo da atividade. Se a atividade tiver
nunca existiu antes, o valor do objeto Bundle
será nulo.
Se você tiver um componente com reconhecimento de ciclo de vida ligado ao ciclo de vida de
sua atividade, ele recebe
ON_CREATE
evento. O método com a anotação @OnLifecycleEvent
é chamado para que seu ciclo de vida reconheça
pode executar qualquer código de configuração necessário para o estado criado.
Este exemplo do método onCreate()
mostra a configuração fundamental da atividade, como declarar a interface do usuário
(definido em um arquivo de layout XML), definir variáveis de membro e configurar
parte da interface. Neste exemplo, o arquivo de layout XML passa a
ID de recurso do arquivo R.layout.main_activity
para
setContentView()
.
Kotlin
lateinit var textView: TextView // Some transient state for the activity instance. var gameState: String? = null override fun onCreate(savedInstanceState: Bundle?) { // Call the superclass onCreate to complete the creation of // the activity, like the view hierarchy. super.onCreate(savedInstanceState) // Recover the instance state. gameState = savedInstanceState?.getString(GAME_STATE_KEY) // Set the user interface layout for this activity. // The layout is defined in the project res/layout/main_activity.xml file. setContentView(R.layout.main_activity) // Initialize member TextView so it is available later. textView = findViewById(R.id.text_view) } // This callback is called only when there is a saved instance previously saved using // onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally // be restored here, possibly usable after onStart() has completed. // The savedInstanceState Bundle is same as the one used in onCreate(). override fun onRestoreInstanceState(savedInstanceState: Bundle?) { textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY) } // Invoked when the activity might be temporarily destroyed; save the instance state here. override fun onSaveInstanceState(outState: Bundle?) { outState?.run { putString(GAME_STATE_KEY, gameState) putString(TEXT_VIEW_KEY, textView.text.toString()) } // Call superclass to save any view hierarchy. super.onSaveInstanceState(outState) }
Java
TextView textView; // Some transient state for the activity instance. String gameState; @Override public void onCreate(Bundle savedInstanceState) { // Call the superclass onCreate to complete the creation of // the activity, like the view hierarchy. super.onCreate(savedInstanceState); // Recover the instance state. if (savedInstanceState != null) { gameState = savedInstanceState.getString(GAME_STATE_KEY); } // Set the user interface layout for this activity. // The layout is defined in the project res/layout/main_activity.xml file. setContentView(R.layout.main_activity); // Initialize member TextView so it is available later. textView = (TextView) findViewById(R.id.text_view); } // This callback is called only when there is a saved instance previously saved using // onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally // be restored here, possibly usable after onStart() has completed. // The savedInstanceState Bundle is same as the one used in onCreate(). @Override public void onRestoreInstanceState(Bundle savedInstanceState) { textView.setText(savedInstanceState.getString(TEXT_VIEW_KEY)); } // Invoked when the activity might be temporarily destroyed; save the instance state here. @Override public void onSaveInstanceState(Bundle outState) { outState.putString(GAME_STATE_KEY, gameState); outState.putString(TEXT_VIEW_KEY, textView.getText()); // Call superclass to save any view hierarchy. super.onSaveInstanceState(outState); }
Como alternativa à definição do arquivo XML e à transmissão dele para setContentView()
, você
pode criar novos objetos View
no seu código de atividade e criar um
hierarquia de visualização inserindo novos objetos View
em uma
ViewGroup
. Em seguida, você usa esse layout passando o atributo
raiz de ViewGroup
para setContentView()
.
Para obter mais informações sobre como criar uma interface do usuário, consulte a
documentação da interface do usuário.
Sua atividade não permanece no console
estado. Depois que o método onCreate()
termina a execução, a atividade entra no estado Started.
e o sistema chama o método onStart()
e onResume()
em métodos rápidos
sucessão.
onStart()
Quando a atividade entra no estado Iniciado, o sistema
invoca onStart()
.
Essa chamada torna a atividade visível para o usuário, pois o
prepara a atividade para entrar em primeiro plano e se tornar interativa.
Por exemplo, é nesse método que o código que mantém
a IU for inicializada.
Quando a atividade é movida para o estado Iniciado, qualquer componente com reconhecimento de ciclo de vida vinculado
ao ciclo de vida da atividade recebe
evento ON_START
.
O método onStart()
é concluído
rapidamente e, como no estado Criado, a atividade não permanece
no estado Iniciado. Quando esse callback termina, a atividade insere o
Retomado e o sistema invoca o
onResume()
.
onResume()
Quando a atividade entra no estado Retomado, ela fica em primeiro plano e
o sistema invoca a classe onResume()
o retorno de chamada. É nesse estado que o aplicativo interage com o usuário. O aplicativo permanece nesse estado até que algo aconteça
tirar o foco do aplicativo, como o dispositivo que está recebendo uma chamada telefônica, o usuário
navegar para outra atividade ou a tela do dispositivo desligar.
Quando a atividade é movida para o estado Retomado, qualquer componente com reconhecimento de ciclo de vida vinculado
ao ciclo de vida da atividade recebe
ON_RESUME
evento. É nesse momento que os componentes do ciclo de vida podem ativar qualquer funcionalidade que precise operar enquanto o componente estiver visível e em primeiro plano, como o início da visualização da câmera.
Quando ocorre um evento de interrupção, a atividade entra no estado Pausado,
e o sistema invoca o
Chamada de retorno onPause()
.
Se a atividade retornar
o estado Retomado do estado Pausado, o sistema chama novamente a função
onResume()
. Por isso, implemente
onResume()
para inicializar os componentes que você libera durante
onPause()
e para realizar qualquer outra
inicializações que devem ocorrer sempre que a atividade entrar no campo
estado.
Este é um exemplo de componente ciente do ciclo de vida que acessa a câmera ao
o componente recebe o evento ON_RESUME
:
Kotlin
class CameraComponent : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun initializeCamera() { if (camera == null) { getCamera() } } ... }
Java
public class CameraComponent implements LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void initializeCamera() { if (camera == null) { getCamera(); } } ... }
O código anterior inicializa a câmera depois que a
LifecycleObserver
recebe o evento ON_RESUME
. No entanto, no modo de várias janelas, sua atividade
poderá ser totalmente visível mesmo quando estiver no estado Pausado. Por exemplo, quando
o app está no modo de várias janelas e o usuário toca na janela que não
contiverem sua atividade, ela será movida para o estado Pausado.
Se você
ativar a câmera apenas quando o app for retomado (visível
e ativa em primeiro plano), depois inicialize a câmera após o
ON_RESUME
evento
demonstradas anteriormente. Se você quiser manter a câmera ativa durante a atividade
estiver pausada, mas visível, como no modo de várias janelas, e
inicializar a câmera após o evento ON_START
.
No entanto, ter a câmera ativo enquanto sua atividade estiver Pausada pode negar o acesso à câmera para outra pessoa App retomado no modo de várias janelas. Às vezes, é necessário manter câmera ativa enquanto sua atividade está Pausada, mas pode prejudicar o a experiência geral do usuário se você fizer isso.
Por isso, pense cuidadosamente sobre onde é mais apropriado assumir o controle dos recursos compartilhados do sistema no contexto do modo de várias janelas. Para saber mais sobre como oferecer suporte ao modo de várias janelas consulte Suporte a várias janelas.
Independentemente de qual evento de construção você escolher para executar uma operação de inicialização, certifique-se de usar o evento de ciclo de vida correspondente para liberar o recurso. Se você inicializar algo depois
o evento ON_START
, libere ou encerre-o após a
ON_STOP
. Se você
é inicializado após o evento ON_RESUME
, depois libere após o
ON_PAUSE
.
O snippet de código anterior coloca o código de inicialização da câmera em uma
com reconhecimento de ciclo de vida. Em vez disso, você pode colocar esse código diretamente na atividade
callbacks do ciclo de vida, como onStart()
e
onStop()
, mas não recomendamos isso. Adicionar essa lógica
a um componente independente e com reconhecimento de ciclo de vida permite reutilizar o componente
em várias atividades sem precisar duplicar o código. Para aprender como criar um componente com reconhecimento de ciclo de vida, consulte
Como gerenciar ciclos de vida com componentes que os reconhecem.
onPause()
O sistema chama esse método como a primeira indicação de que o usuário está saindo sua atividade, embora isso não signifique sempre que ela será destruída. Isso indica que a atividade não está mais em primeiro plano, mas está ainda ficará visível se o usuário estiver no modo de várias janelas. Há vários motivos pelos quais uma atividade pode entrar este estado:
- É um evento que interrompe a execução do app, conforme descrito na seção sobre callback onResume(), pausa a atividade atual. Esse é o caso mais comum.
- No modo de várias janelas, apenas um app tem foco a qualquer momento, e o sistema pausa todos os outros aplicativos.
- A abertura de uma nova atividade semitransparente, como uma caixa de diálogo, pausa a atividade coberta. Enquanto se a atividade estiver parcialmente visível, mas não em foco, ela permanece pausada.
Quando uma atividade é movida para o estado Pausado, qualquer componente com reconhecimento de ciclo de vida vinculado
ao ciclo de vida da atividade recebe
evento ON_PAUSE
. É nesse momento que os componentes do ciclo de vida podem interromper qualquer funcionalidade que não precise operar enquanto o componente não estiver em primeiro plano, como na pausa de uma visualização da câmera.
Use o método onPause()
para pausar ou
ajustar operações que não podem continuar ou que possam continuar com moderação;
enquanto o Activity
está no estado Pausado e você
serão retomados em breve.
Também é possível usar o método onPause()
para
liberar recursos do sistema, processá-los para sensores (como GPS) ou outros recursos
afetar a duração da bateria enquanto sua atividade estiver Pausada e o usuário não
precisar deles.
No entanto, como mencionado na seção sobre onResume()
, um status de pausa
a atividade ainda pode ficar totalmente visível se o app estiver no modo de várias janelas.
Considere usar onStop()
em vez de onPause()
para liberar ou ajustar totalmente
recursos e operações relacionados à interface para oferecer melhor suporte ao modo de várias janelas.
O exemplo a seguir de um LifecycleObserver
reagindo ao evento ON_PAUSE
é a contraparte do evento
Exemplo de evento ON_RESUME
, liberando a câmera que é inicializada depois
o evento ON_RESUME
for recebido:
Kotlin
class CameraComponent : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun releaseCamera() { camera?.release() camera = null } ... }
Java
public class JavaCameraComponent implements LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void releaseCamera() { if (camera != null) { camera.release(); camera = null; } } ... }
Este exemplo coloca o código de liberação da câmera após o
O evento ON_PAUSE
é recebido pelo LifecycleObserver
.
A execução de onPause()
é muito breve e
não oferece necessariamente tempo suficiente para realizar operações de salvamento. Para isso
não use onPause()
para salvar o aplicativo ou o
fazer chamadas de rede ou executar transações de banco de dados. Esse trabalho pode não
ser concluído antes da conclusão do método.
Em vez disso, execute operações pesadas de desligamento durante
onStop()
: Para mais informações
sobre operações adequadas para realizar
onStop()
, consulte a próxima seção. Para mais informações sobre como salvar
dados, consulte a seção sobre como salvar e restaurar o estado.
A conclusão do método onPause()
não significa que a atividade saia do estado "Pausado". Em vez disso, a atividade
permanece nesse estado até que a atividade seja retomada ou se torne totalmente
fica invisível para o usuário. Se a atividade for retomada, o sistema invocará mais uma vez o callback onResume()
.
Se o
atividade retorna do estado Pausado para o Retomado, o sistema mantém
à instância Activity
residente na memória, recuperando
essa instância quando o sistema invocar onResume()
.
Neste cenário, não é necessário reinicializar componentes criados durante
métodos de callback que levam ao estado Retomado. Se a atividade se tornar
completamente invisível, o sistema chama
onStop()
:
onStop()
Quando sua atividade não está mais visível para o usuário, ela entra no
Parado, e o sistema invoca o
Chamada de retorno onStop()
. Isso pode ocorrer quando uma atividade recém-iniciada cobre toda a tela. A
o sistema também chama onStop()
quando a atividade termina de ser executada e está prestes a ser encerrada.
Quando a atividade é movida para o estado Interrompido, qualquer componente com reconhecimento de ciclo de vida vinculado
ao ciclo de vida da atividade recebe
evento ON_STOP
. É nesse momento que os componentes do ciclo de vida podem interromper qualquer funcionalidade que não precise operar enquanto o componente não estiver visível na tela.
No método onStop()
, solte ou ajuste
recursos desnecessários enquanto o app não está visível ao usuário. Por exemplo, o aplicativo poderá pausar animações ou alternar de atualizações de local mais específicas para as menos detalhadas. Usando
onStop()
em vez de onPause()
significa que o trabalho relacionado à interface continua, mesmo quando o usuário está visualizando sua atividade no modo de várias janelas
modo
Além disso, use onStop()
para executar operações de desligamento com uso relativamente intensivo da CPU. Por exemplo, se
não consegue encontrar um momento melhor para salvar informações em um banco de dados,
poderá fazer isso durante onStop()
. O exemplo abaixo mostra uma implementação de onStop()
que salva o conteúdo de uma nota de rascunho no armazenamento persistente:
Kotlin
override fun onStop() { // Call the superclass method first. super.onStop() // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. val values = ContentValues().apply { put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()) put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()) } // Do this update in background on an AsyncQueryHandler or equivalent. asyncQueryHandler.startUpdate( token, // int token to correlate calls null, // cookie, not used here uri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. ) }
Java
@Override protected void onStop() { // Call the superclass method first. super.onStop(); // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. ContentValues values = new ContentValues(); values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()); values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()); // Do this update in background on an AsyncQueryHandler or equivalent. asyncQueryHandler.startUpdate ( mToken, // int token to correlate calls null, // cookie, not used here uri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. ); }
O exemplo de código anterior usa o SQLite diretamente. No entanto, recomendamos usar o Room, uma biblioteca de persistência que fornece uma camada de abstração sobre o SQLite. Para saber sobre os benefícios de usar o Room e como implementá-lo no seu app consulte Biblioteca de persistência Room guia.
Quando a atividade entra no estado Interrompido, o Activity
é mantido na memória: ele mantém todos os elementos de estado
informações, mas não está anexado ao gerenciador de janelas. Quando a atividade
de currículos, ele lembra essas informações.
Você não precisa
reinicializar componentes criados durante qualquer um dos métodos de callback
que levam ao estado Retomado. O sistema também monitora
estado para cada objeto View
no layout. Portanto, se o
o usuário digita texto em um widget EditText
, que
conteúdo é retido e não precisa ser salvo nem restaurado.
Observação: quando a atividade for interrompida, o sistema poderá destruir o processo que contém a atividade se precisar recuperar a memória.
Mesmo que o sistema destrua o processo enquanto a atividade
for interrompido, o sistema ainda manterá o estado do View
;
objetos, como texto em um widget EditText
, em um
Bundle
: um blob de pares de chave-valor, e os restaura.
se o usuário navegar de volta para a atividade. Para
mais informações sobre como restaurar uma atividade para a qual um usuário retorna, consulte o
sobre como salvar e restaurar o estado.
A partir do estado "Interrompido", a atividade volta a interagir com o usuário ou para de operar e é encerrada. Se a atividade voltar, o sistema invocará onRestart()
.
Caso a Activity
deixe de operar, o sistema chamará onDestroy()
.
onDestroy()
onDestroy()
é chamado antes de a atividade ser destruída. O sistema invoca esse callback por um destes dois motivos:
-
A atividade está sendo finalizada, porque o usuário descartou completamente o
atividade ou devido a
finish()
sendo seja chamado na atividade. - O sistema está destruindo temporariamente a atividade devido a uma configuração mudar, como girar o dispositivo ou entrar no modo de várias janelas.
Quando a atividade é movida para o estado destruído, qualquer componente ciente do ciclo de vida vinculado
ao ciclo de vida da atividade recebe
evento ON_DESTROY
. É aqui que
os componentes do ciclo de vida podem limpar tudo que precisam antes
Activity
será destruído.
Em vez de colocar lógica à Activity
para determinar por que ela está sendo destruída,
use um objeto ViewModel
para conter o
dados de visualização relevantes da sua Activity
. Se a Activity
for recriada
devido a uma mudança de configuração, o ViewModel
não precisa fazer nada, já que
ele é preservado e dado à próxima instância de Activity
.
Se a Activity
não for recriada, a ViewModel
terá a
método onCleared()
chamado, em que
ele pode limpar todos os dados necessários antes de ser destruído. É possível distinguir entre esses dois cenários com a
método isFinishing()
.
Se a atividade estiver sendo finalizada, onDestroy()
será o callback do ciclo de vida final que o
a atividade recebe. Se onDestroy()
for chamado como resultado de uma configuração
mudar, o sistema cria imediatamente uma nova instância de atividade e chama
onCreate()
na nova instância na nova configuração.
O callback onDestroy()
libera todos os recursos ainda não liberados
de callbacks, como onStop()
.
Estado da atividade e ejeção da memória
O sistema encerra processos quando precisa liberar RAM. A probabilidade do sistema eliminar um determinado processo depende do estado dele no momento. O estado do processo, por sua vez, depende do estado da atividade em execução no processo. A tabela 1 mostra as correlações entre o estado do processo, a atividade estado e a probabilidade de o sistema encerrar o processo. Esta tabela só se aplica se um processo não estiver executando outros tipos de componentes de aplicativos.
Probabilidade de eliminação | Estado do processo | Estado da atividade final |
---|---|---|
Mais baixa | Em primeiro plano (com foco ou prestes a ter) | Retomado |
Baixa | Visível (sem foco) | Iniciado/pausado |
Alto | Segundo plano (invisível) | Parado |
Mais alta | Vazio | Destruído |
Tabela 1. Relação entre o ciclo de vida do processo e o estado da atividade.
O sistema nunca elimina uma atividade diretamente para liberar memória. Em vez disso, encerra o processo em que a atividade é executada, destruindo não apenas a atividade mas tudo o mais em execução no processo também. Para saber como preservar e restaurar o estado da interface da atividade quando o processo for encerrado pelo sistema ocorrer, consulte a seção sobre como salvar e restaurar o estado.
O usuário também pode encerrar um processo usando o Gerenciador de aplicativos, em Configurações, para encerrar o app correspondente.
Para mais informações sobre processos, consulte Processos e linhas de execução geral do Google.
Como salvar e restaurar o estado transitório da IU
O usuário espera que o estado da IU de uma atividade permaneça o mesmo durante uma mudança de configuração, como rotação ou alternar para o modo de várias janelas. No entanto, o sistema destrói a atividade por padrão quando ocorre uma mudança de configuração. Isso exclui qualquer estado de IU armazenado na instância da atividade.
Da mesma forma, um usuário espera que o estado da IU permaneça o mesmo se ele alternar temporariamente do seu aplicativo para outro e retornar ao inicial posteriormente. No entanto, o sistema pode destruir o processo do aplicativo enquanto os o usuário está ausente e a sua atividade é interrompida.
Quando as restrições do sistema destroem a atividade, preserve a
o estado transitório da interface do usuário usando uma combinação de
ViewModel
,
onSaveInstanceState()
,
e/ou armazenamento local. Para saber mais sobre as expectativas do usuário em comparação com o sistema
comportamento do usuário e a melhor maneira de preservar dados complexos de estado da interface em
atividade iniciada pelo sistema e encerramento do processo, consulte
Salvar estados da interface.
Esta seção descreve o que é o estado da instância e como implementar a
onSaveInstance()
, que é um callback na própria atividade. Se as
Os dados da interface são leves. Você pode usar o onSaveInstance()
sozinho para manter a interface.
o estado nas mudanças de configuração e no encerramento do processo iniciado pelo sistema.
Mas, como onSaveInstance()
incorre em custos de serialização/desserialização,
na maioria dos casos, você usa ViewModel
e onSaveInstance()
, já que
descritos em
Salvar estados da interface.
Observação : para saber mais sobre mudanças de configuração, veja como restringir atividades recriação, se necessário, e como reagir a essas mudanças de configuração da Visualize o sistema e o Jetpack Compose, confira o Página Gerenciar mudanças de configuração.
Estado da instância
Há alguns casos em que a atividade é destruída devido ao comportamento normal do aplicativo, como quando o usuário pressiona o botão "Voltar" ou a atividade sinaliza a própria destruição chamando o método finish()
.
Quando sua atividade é destruída porque o usuário pressiona "Voltar"
ou a atividade se encerra, o conceito do sistema e do usuário
essa instância do Activity
desapareceu para sempre. Nessas
cenários, a expectativa do usuário corresponde ao comportamento do sistema, e você não
ainda há algum trabalho extra a fazer.
No entanto, se o sistema destruir a atividade devido a restrições do sistema (como
uma mudança de configuração ou pressão de memória),
Activity
instância for perdida, o sistema lembrará que ela existiu. Se o usuário tentar navegar de volta para a atividade, o sistema criará uma nova instância dela usando um conjunto de dados salvos que descrevem o estado da atividade quando ela foi destruída.
Os dados salvos que o sistema usa para restaurar o
o estado anterior é chamado de estado da instância. É uma coleção de
pares de chave-valor armazenados em um objeto Bundle
. Por padrão, o
O sistema usa o estado da instância Bundle
para salvar informações
sobre cada objeto View
no layout da atividade, como
o valor de texto inserido em um
Widget EditText
.
Assim, se a instância da atividade for destruída e recriada, o estado do layout será restaurado para o estado anterior sem que haja necessidade de código. No entanto, a atividade pode conter mais informações de estado do que se quer restaurar, como variáveis de associação que rastreiam o progresso do usuário na atividade.
Observação: para que o sistema Android restaure o estado das visualizações na atividade, cada uma delas precisa ter um código exclusivo, fornecido pelo atributo android:id
.
Um objeto Bundle
não é apropriado para preservar mais do que uma
uma quantidade trivial de dados, porque requer serialização na linha de execução principal e consome
e a memória de processos do sistema. Para preservar mais do que uma quantidade muito pequena de dados,
adotar uma abordagem combinada para preservar dados, usando
o armazenamento, o método onSaveInstanceState()
e o
ViewModel
, conforme descrito em
Salvar estados da interface.
Salvar estados de IU leves e simples com onSaveInstanceState()
À medida que a atividade começar a parar, o sistema chama o método onSaveInstanceState()
para que ela possa salvar a informação do estado em um pacote de estado da instância. A implementação padrão desse método salva informações transitórias sobre o estado da hierarquia de visualização da atividade, como o texto em um widget EditText
ou a posição de rolagem de um ListView
.
Para salvar outras informações sobre o estado da instância para sua atividade, modifique
onSaveInstanceState()
e adicione pares de chave-valor ao objeto Bundle
salvo.
caso sua atividade seja destruída inesperadamente. Quando você substitui
onSaveInstanceState()
, você precisa chamar a implementação de superclasse
se você quiser que a implementação padrão salve o estado da hierarquia de visualização.
Isso é mostrado neste exemplo:
Kotlin
override fun onSaveInstanceState(outState: Bundle?) { // Save the user's current game state. outState?.run { putInt(STATE_SCORE, currentScore) putInt(STATE_LEVEL, currentLevel) } // Always call the superclass so it can save the view hierarchy state. super.onSaveInstanceState(outState) } companion object { val STATE_SCORE = "playerScore" val STATE_LEVEL = "playerLevel" }
Java
static final String STATE_SCORE = "playerScore"; static final String STATE_LEVEL = "playerLevel"; // ... @Override public void onSaveInstanceState(Bundle savedInstanceState) { // Save the user's current game state. savedInstanceState.putInt(STATE_SCORE, currentScore); savedInstanceState.putInt(STATE_LEVEL, currentLevel); // Always call the superclass so it can save the view hierarchy state. super.onSaveInstanceState(savedInstanceState); }
Observação :
onSaveInstanceState()
não é
chamados quando o usuário fecha explicitamente a atividade ou em outros casos quando
finish()
for chamado.
Para salvar dados persistentes, como preferências do usuário ou dados para um banco de dados,
aproveitar as oportunidades adequadas quando a atividade estiver em primeiro plano.
Se essas oportunidades não surgirem, salve os dados persistentes durante a
método onStop()
.
Restaurar o estado de IU da atividade por meio de um estado da instância salvo
Quando a atividade é recriada depois de ter sido destruída, é possível recuperar o estado salvo do Bundle
que o sistema passou para a atividade. Tanto o
onCreate()
e
onRestoreInstanceState()
os métodos de callback recebem o mesmo Bundle
que contém a
informações de estado da instância.
Como o método onCreate()
é
chamado se o sistema está criando uma nova instância da atividade
ou recriar uma anterior, é preciso verificar se o estado Bundle
é nulo antes de você tentar fazer a leitura. Se for nulo, o sistema criará uma nova instância da atividade em vez de restaurar uma anterior que tenha sido destruída.
O snippet de código a seguir mostra como restaurar alguns
dados de estado em onCreate()
:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Always call the superclass first // Check whether we're recreating a previously destroyed instance. if (savedInstanceState != null) { with(savedInstanceState) { // Restore value of members from saved state. currentScore = getInt(STATE_SCORE) currentLevel = getInt(STATE_LEVEL) } } else { // Probably initialize members with default values for a new instance. } // ... }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Always call the superclass first // Check whether we're recreating a previously destroyed instance. if (savedInstanceState != null) { // Restore value of members from saved state. currentScore = savedInstanceState.getInt(STATE_SCORE); currentLevel = savedInstanceState.getInt(STATE_LEVEL); } else { // Probably initialize members with default values for a new instance. } // ... }
Em vez de restaurar o estado durante
onCreate()
, é possível implementar
onRestoreInstanceState()
, que o sistema chama após o
onStart()
. O sistema chama
onRestoreInstanceState()
apenas se houver um estado salvo para restaurar. Portanto,
não é necessário verificar se Bundle
é nulo.
Kotlin
override fun onRestoreInstanceState(savedInstanceState: Bundle?) { // Always call the superclass so it can restore the view hierarchy. super.onRestoreInstanceState(savedInstanceState) // Restore state members from saved instance. savedInstanceState?.run { currentScore = getInt(STATE_SCORE) currentLevel = getInt(STATE_LEVEL) } }
Java
public void onRestoreInstanceState(Bundle savedInstanceState) { // Always call the superclass so it can restore the view hierarchy. super.onRestoreInstanceState(savedInstanceState); // Restore state members from saved instance. currentScore = savedInstanceState.getInt(STATE_SCORE); currentLevel = savedInstanceState.getInt(STATE_LEVEL); }
Cuidado: sempre chame a implementação de superclasse de
onRestoreInstanceState()
para que a implementação padrão restaure o estado da hierarquia de visualização.
Como navegar entre as atividades
É provável que um aplicativo entre e saia de uma atividade, talvez muitas vezes, durante a ciclo de vida do app, como quando o usuário toca no botão "Voltar" do dispositivo ou a atividade inicia uma atividade diferente.
Esta seção aborda os tópicos que você precisa conhecer para implementar transições de atividades corretamente. Esses tópicos incluem iniciar uma atividade a partir de outra, salvar e restaurar o estado da atividade.
Como iniciar uma atividade a partir de outra
Uma atividade frequentemente precisa iniciar outra em algum momento. Essa necessidade surge, por exemplo, quando um aplicativo precisa ser movido da tela atual para uma nova.
Dependendo se sua atividade quer ou não um resultado da nova atividade,
estiver prestes a começar, inicie a nova atividade usando o
startActivity()
ou o
startActivityForResult()
. De qualquer forma, passe um objeto Intent
.
O objeto Intent
especifica o objeto exato
atividade que você deseja iniciar ou descreve o tipo de ação que você deseja realizar.
O sistema seleciona a atividade adequada para você, que pode
de um aplicativo diferente. Um objeto Intent
também pode carregar pequenas quantidades de dados que serão usados pela atividade iniciada.
Para mais informações sobre a classe Intent
, consulte Intents e filtros de intents.
startActivity()
Se a atividade recém-criada não precisar retornar um resultado, a atividade atual poderá iniciá-la chamando o método startActivity()
.
Ao trabalhar no aplicativo, frequentemente será necessário iniciar uma atividade conhecida.
Por exemplo, o snippet de código a seguir mostra como iniciar uma atividade chamada SignInActivity
.
Kotlin
val intent = Intent(this, SignInActivity::class.java) startActivity(intent)
Java
Intent intent = new Intent(this, SignInActivity.class); startActivity(intent);
Seu aplicativo também pode precisar realizar alguma ação, como enviar um e-mail, uma mensagem de texto ou atualização de status, usando os dados da atividade. Nesse caso, o aplicativo pode não ter as próprias atividades para executar esse tipo de ação. Assim, você pode aproveitar as atividades fornecidas por outros aplicativos do dispositivo que podem executar essas ações.
É aqui que as intents são muito valiosas. É possível criar um que descreve uma ação que você quer realizar e o sistema inicia a ação atividades de outro aplicativo. Se houver mais de uma atividade que possa processar a intent, o usuário poderá escolher qual usará. Por exemplo, se você quer permitir que o usuário envie um será possível criar a seguinte intent:
Kotlin
val intent = Intent(Intent.ACTION_SEND).apply { putExtra(Intent.EXTRA_EMAIL, recipientArray) } startActivity(intent)
Java
Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); startActivity(intent);
O EXTRA_EMAIL
extra adicionado à intent é uma matriz de strings de
endereços de e-mail para os quais o e-mail será enviado. Quando um aplicativo de e-mail
responde a essa intent, ele lê a matriz de strings fornecida nas sub-redes
coloca os endereços no campo "to" do formulário de composição do e-mail. Neste
situação, a atividade do aplicativo de e-mail começa e, quando o usuário termina,
seus currículos de atividade.
startActivityForResult()
Às vezes, você precisa receber um resultado de uma atividade quando ela é encerrada. Por exemplo, você pode começar
uma atividade que permite ao usuário escolher uma pessoa em uma lista de contatos. Quando termina, ele retorna o
pessoa selecionada. Para fazer isso, chame o método startActivityForResult(Intent, int)
, em que o parâmetro inteiro identifica a chamada.
Esse identificador distingue-se entre várias chamadas para
startActivityForResult(Intent, int)
da mesma atividade. Não é um identificador global
e não corre o risco de entrar em conflito com outros apps ou atividades. O resultado é retornado pela
onActivityResult(int, int, Intent)
.
Quando há atividade filha, ela pode chamar setResult(int)
para retornar os dados à atividade pai.
A atividade filha precisa fornecer um código de resultado, que pode ser o resultado padrão
RESULT_CANCELED
, RESULT_OK
ou qualquer valor personalizado
a partir de RESULT_FIRST_USER
.
Além disso,
a atividade filha pode retornar uma Intent
que contém qualquer dado adicional que desejar. A atividade pai usa o
onActivityResult(int, int, Intent)
, junto com o identificador inteiro da atividade pai originalmente
para receber as informações.
Se houver uma falha na atividade filha por qualquer motivo, a atividade pai receberá um resultado com o código RESULT_CANCELED
.
Kotlin
class MyActivity : Activity() { // ... override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { // When the user center presses, let them pick a contact. startActivityForResult( Intent(Intent.ACTION_PICK,Uri.parse("content://contacts")), PICK_CONTACT_REQUEST) return true } return false } override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) { when (requestCode) { PICK_CONTACT_REQUEST -> if (resultCode == RESULT_OK) { // A contact was picked. Display it to the user. startActivity(Intent(Intent.ACTION_VIEW, intent?.data)) } } } companion object { internal val PICK_CONTACT_REQUEST = 0 } }
Java
public class MyActivity extends Activity { // ... static final int PICK_CONTACT_REQUEST = 0; public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { // When the user center presses, let them pick a contact. startActivityForResult( new Intent(Intent.ACTION_PICK, new Uri("content://contacts")), PICK_CONTACT_REQUEST); return true; } return false; } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_CONTACT_REQUEST) { if (resultCode == RESULT_OK) { // A contact was picked. Display it to the user. startActivity(new Intent(Intent.ACTION_VIEW, data)); } } } }
Coordenação de atividades
Quando uma atividade inicia outra, ambas passam por transições no ciclo de vida. A primeira atividade para de operar e entra no estado "Pausado" ou "Interrompido" enquanto a outra atividade é criada. Caso essas atividades compartilhem dados salvos em disco ou em outro lugar, é importante compreender que a primeira atividade não é totalmente interrompida antes da criação da segunda. Em vez disso, o processo de iniciar a segunda se sobrepõe ao processo de interromper a primeira.
A ordem dos callbacks do ciclo de vida é bem definida, especialmente quando as duas atividades são no mesmo processo — ou seja, no mesmo app — e uma inicia a outra. Esta é a ordem das operações que ocorrem quando a atividade A inicia a atividade B:
- O método
onPause()
da atividade A é executado. - Os métodos
onCreate()
,onStart()
eonResume()
da atividade B são executados em sequência A atividade B agora tem o foco do usuário. - Se a atividade A não estiver mais visível na tela, o método
onStop()
dela será executado.
Essa sequência de callbacks do ciclo de vida permite gerenciar a transição informações de uma atividade para outra.