Quando exatamente onSaveInstanceState () e onRestoreInstanceState () são chamados?

102

A figura a seguir (do documento oficial ) descreve o conhecido ciclo de vida de uma atividade Android:

insira a descrição da imagem aqui

Por outro lado, quando a atividade é destruída pelo sistema (por exemplo, porque a memória precisa ser recuperada), o estado da atividade às vezes é automaticamente salvo e restaurado por meio dos métodos onSaveInstanceState()e onRestoreInstanceState(), conforme ilustrado pela figura a seguir (também do documento oficial ):

insira a descrição da imagem aqui

Estou ciente de que onSaveInstanceState()é nem sempre chamado quando uma atividade está prestes a ser destruído. Por exemplo, se for destruído porque o usuário pressionou o botão "voltar", o estado de atividade não é preservado. Mas nos casos em que o estado é salvo e restaurado e onSaveInstanceState()/ onRestoreInstanceState()é chamado, quando exatamente eles são chamados ?

Por exemplo, de acordo com as figuras acima, onRestoreInstanceState()pode ser chamado antes onStart()ou depois, onStart()mas antes onResume()ou depois onResume(). Da mesma forma, existem várias possibilidades para onSaveInstanceState(). Então, quando eles são chamados exatamente?

Idealmente, o que eu gostaria é ver um diagrama combinado mostrando os estados do ciclo de vida da atividade e os métodos de salvar / restaurar , se houver.

Luis mendo
fonte
obteve a resposta final do documento oficial do Android, onSaveInstanceState () chamado entre onPause () e onStop ().
Rishi
1
@Rishi Você pode fornecer um link para esse documento?
Luis Mendo
leia Salve seu parágrafo de estado de atividade lá
Rishi
se estou correto ou não, esclareça
Rishi

Respostas:

107

Pela documentação :

void onRestoreInstanceState (Bundle savedInstanceState)

Este método é chamado entre onStart()e onPostCreate(Bundle).

void onSaveInstanceState (Bundle outState)

Se chamado, este método ocorrerá após onStop () para aplicativos direcionados a plataformas começando com Build.VERSION_CODES.P. Para aplicativos que visam versões anteriores da plataforma, este método ocorrerá antes de onStop () e não há garantias sobre se ocorrerá antes ou depois de onPause ().

Steve M
fonte
1
Obrigado. Você poderia fornecer os links para a documentação?
Luis Mendo
Pronto, também não acho que haja mais nada entre onStart () e onPostCreate (), então onRestoreInstanceState () está bem definido na cadeia.
Steve M
Muito obrigado. Isso esclarece a questão
Luis Mendo
1
@SteveM "Não há garantias sobre se isso ocorrerá antes ou depois de onPause ()" Isso significa que se tentarmos acessar uma visualização (para obter algum valor para salvar, como um índice de uma visualização de lista), poderemos encontrar NullPointerExceptions?
Tiago
3
Então, o que é recomendado, salvar uma estrutura de dados em onPause e restaurá-la em onResume em vez de onSaveInstanceState e onRestoreInstanceState?
Gödel77
18

Como por doc1 e doc2

onSaveInstanceState

Antes do Honeycomb, as atividades não eram consideradas elimináveis ​​até que fossem pausadas, o que significa que onSaveInstanceState () era chamado imediatamente antes de onPause (). Começando com o Honeycomb, no entanto, as Atividades são consideradas elimináveis ​​somente após terem sido interrompidas, o que significa que onSaveInstanceState () agora será chamado antes de onStop () em vez de imediatamente antes de onPause ().

onRestoreInstanceState

Este método é chamado entre onStart () e onPostCreate (Bundle) quando a atividade está sendo reinicializada a partir de um estado salvo anteriormente

Desenvolvedor Android
fonte
gostou da maneira como você descreveu cenários em diferentes versões do Android
Jimit Patel
14

Além das respostas já postadas, há uma mudança sutil introduzida no Android P, que é:

void onSaveInstanceState (Bundle outState)

Se chamado, este método vai ocorrer APÓS onStop() para aplicações de segmentação plataformas começando com P . Para aplicativos que visam versões anteriores da plataforma, esse método ocorrerá antes onStop()e não há garantias sobre se ocorrerá antes ou depois onPause().

Fonte: docs

Quanto ao motivo dessa mudança, aqui está a resposta:

... assim, um aplicativo pode realizar transações de fragmento com segurança onStop()e poderá salvar o estado persistente posteriormente.

Fonte: docs

azizbekian
fonte
Oi, ótimo comentário. Você sabe como se comportará o aplicativo que P alvo, mas é executado em API inferior? O mesmo que o aplicativo que visa API inferior ou será consistente em toda a api e manterá o comportamento de "API de segmentação"?
Filipkowicz
@Filipkowicz, Do you know how will behave app that target P but runs on lower api?Enquanto o aplicativo estiver sendo executado, digamos, no M, a versão do Android que este dispositivo possui não contém alterações, que são introduzidas em P, o que significa que independentemente de você ter especificado o alvo, Pvocê não verá diferente para dispositivos pré-P. espero que isso responda sua pergunta.
azizbekian
Eu me sinto tão relaxado hoje depois de ler esta resposta, porque eu estava fazendo o curso gratuito do Android no Udacity e eles ainda têm a versão antiga dos tutoriais que afirmam no exercício 8 da lição 5 que os métodos onStop e onDestroy não deveriam estar lá no textView exibido. Mas eu não sabia que era para as versões mais antigas do android e estava executando meu aplicativo no android pie e estava recebendo o método onStop no meu textView. Muito obrigado. Finalmente me sentindo bem.
Sandhu
6

Esta é uma informação extra para onSaveInstanceState (Bundle)

de docs

Não confunda esse método com callbacks do ciclo de vida da atividade, como onPause (), que é sempre chamado quando uma atividade está sendo colocada em segundo plano ou a caminho da destruição, ou onStop () que é chamado antes da destruição. Um exemplo de quando onPause () e onStop () são chamados e não este método é quando um usuário navega de volta da atividade B para a atividade A: não há necessidade de chamar onSaveInstanceState (Bundle) em B porque essa instância específica nunca será restaurada , então o sistema evita chamá-lo. Um exemplo quando onPause () é chamado e não onSaveInstanceState (Bundle) é quando a atividade B é iniciada na frente da atividade A: o sistema pode evitar chamar onSaveInstanceState (Bundle) na atividade A se não for eliminado durante a vida de B desde o estado da interface do usuário de A permanecerá intacto.

Portanto, é a implementação padrão para ..

A implementação padrão cuida da maior parte do estado da IU por instância para você, chamando onSaveInstanceState () em cada visão na hierarquia que tem um id e salvando o id da visão atualmente focada (todos os quais são restaurados pelo implementação padrão de onRestoreInstanceState (Bundle)). Se você substituir esse método para salvar informações adicionais não capturadas por cada visualização individual, provavelmente desejará chamar a implementação padrão, caso contrário, esteja preparado para salvar todo o estado de cada visualização por conta própria.

Mahmoud Mzz
fonte
0
String activityState;
@Override 
public void onCreate(Bundle savedInstanceState) {
// call the super class onCreate to complete the creation of activity like 
// the view hierarchy 
super.onCreate(savedInstanceState);

// recovering the instance state 
if (savedInstanceState != null) {
     activityState = savedInstanceState.getString(STATE_KEY);
 } 

   setContentView(R.layout.main_activity);
   mTextView = (TextView) findViewById(R.id.text_view);
} 

// Este retorno de chamada é chamado apenas quando há uma instância salva anteriormente salva usando // onSaveInstanceState (). Restauramos algum estado em onCreate () enquanto podemos opcionalmente restaurar // outro estado aqui, possivelmente utilizável após onStart () ser concluído. // O pacote savedInstanceState é o mesmo usado em onCreate ().

@Override 
public void onRestoreInstanceState(Bundle savedInstanceState) {
 mTextView.setText(savedInstanceState.getString(STATE_KEY));
  } 


// invoked when the activity may be temporarily destroyed, save the instance 
//state here 
//this method will be called before onstop

@Override 
 public void onSaveInstanceState(Bundle outState) {
    outState.putString(STATE_KEY, activityState);

    // call superclass to save any view hierarchy 
    super.onSaveInstanceState(outState);
} 
Parvez Rafi
fonte
Com licença, como isso responde à pergunta quando os métodos de salvar / restaurar são chamados exatamente ?
Luis Mendo