Ciclo de vida da atividade

À 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.

Figura 1. Ilustração simplificada do ciclo de vida da atividade.

À 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:

  1. A atividade está sendo finalizada, porque o usuário descartou completamente o atividade ou devido a finish() sendo seja chamado na atividade.
  2. 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:

  1. O método onPause() da atividade A é executado.
  2. Os métodos onCreate(), onStart() e onResume() da atividade B são executados em sequência A atividade B agora tem o foco do usuário.
  3. 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.