Estou tentando salvar e restaurar o estado de um Activity
usando os métodos onSaveInstanceState()
e onRestoreInstanceState()
.
O problema é que isso nunca entra no onRestoreInstanceState()
método. Alguém pode me explicar por que isso acontece?
android
android-activity
states
BlaBRA
fonte
fonte
Respostas:
Normalmente, você restaura seu estado em
onCreate()
. Também é possível restaurá-loonRestoreInstanceState()
, mas não é muito comum. (onRestoreInstanceState()
é chamado depoisonStart()
, enquantoonCreate()
é chamado antesonStart()
.Use os métodos put para armazenar valores em
onSaveInstanceState()
:protected void onSaveInstanceState(Bundle icicle) { super.onSaveInstanceState(icicle); icicle.putLong("param", value); }
E restaure os valores em
onCreate()
:public void onCreate(Bundle icicle) { if (icicle != null){ value = icicle.getLong("param"); } }
fonte
onRestoreInstanceState()
é chamado apenas ao recriar a atividade depois de eliminada pelo sistema operacional. Tal situação acontece quando:Em contraste: se você está em sua atividade e acerta
Back
aperta o botão do dispositivo, sua atividade é concluída () ed (ou seja, pense nisso como sair do aplicativo de desktop) e da próxima vez que você iniciar seu aplicativo, ele será iniciado "fresco", ou seja, sem estado salvo porque você saiu dele intencionalmente ao baterBack
.Outra fonte de confusão é que, quando um aplicativo perde o foco, outro aplicativo
onSaveInstanceState()
é chamado, mas quando você navega de volta para o aplicativo, eleonRestoreInstanceState()
pode não ser chamado. Este é o caso descrito na pergunta original, ou seja, se sua atividade NÃO foi interrompida durante o período em que outra atividade estava em sua frenteonRestoreInstanceState()
, NÃO será chamado porque sua atividade está praticamente "viva".Em suma, conforme declarado na documentação para
onRestoreInstanceState()
:Pelo que li: Não há razão para substituir a
onRestoreInstanceState()
menos que você esteja criando uma subclasseActivity
e seja esperado que alguém crie uma subclasse de sua subclasse.fonte
O estado em que você salva
onSaveInstanceState()
está disponível posteriormente naonCreate()
invocação do método. Portanto, useonCreate
(e seuBundle
parâmetro) para restaurar o estado de sua atividade.fonte
Como alternativa, você pode armazenar um pacote com os dados que deseja manter no Intent usado para iniciar a atividade A.
Intent intent = new Intent(this, ActivityA.class); intent.putExtra("bundle", theBundledData); startActivity(intent);
A Atividade A teria que passar isso de volta para a Atividade B. Você recuperaria o intent no método onCreate da Atividade B.
Intent intent = getIntent(); Bundle intentBundle; if (intent != null) intentBundle = intent.getBundleExtra("bundle"); // Do something with the data.
Outra ideia é criar uma classe de repositório para armazenar o estado da atividade e fazer com que cada uma de suas atividades faça referência a essa classe (possível usando uma estrutura singleton). Porém, fazer isso provavelmente é mais problemático do que compensa.
fonte
O principal é que, se você não armazenar
onSaveInstanceState()
,onRestoreInstanceState()
não será chamado. Esta é a principal diferença entrerestoreInstanceState()
eonCreate()
. Certifique-se de realmente armazenar algo. Provavelmente este é o seu problema.fonte
Descobri que onSaveInstanceState é sempre chamado quando outra Activity vem para o primeiro plano. E onStop também.
No entanto, onRestoreInstanceState foi chamado apenas quando onCreate e onStart também foram chamados. E onCreate e onStart NÃO eram sempre chamados.
Portanto, parece que o Android nem sempre exclui as informações de estado, mesmo que a atividade passe para o segundo plano. No entanto, ele chama os métodos de ciclo de vida para salvar o estado apenas por segurança. Portanto, se o estado não for excluído, o Android não chamará os métodos de ciclo de vida para restaurar o estado, pois eles não são necessários.
A Figura 2 descreve isso.
fonte
Acho que este tópico era bastante antigo. Acabei de mencionar outro caso, que
onSaveInstanceState()
também será chamado, é quando você ligaActivity.moveTaskToBack(boolean nonRootActivity)
.fonte
Se você estiver lidando com as mudanças de orientação da atividade com
android:configChanges="orientation|screenSize"
eonConfigurationChanged(Configuration newConfig)
,onRestoreInstanceState()
não será chamado.fonte
Não é necessário que onRestoreInstanceState seja sempre chamado após onSaveInstanceState.
Observe que: onRestoreInstanceState sempre será chamado, quando a atividade for girada (quando a orientação não for controlada) ou abrir sua atividade e, em seguida, abrir outros aplicativos para que sua instância de atividade seja apagada da memória pelo SO.
fonte
Na documentação Restaurar o estado da IU da atividade usando o estado da instância salva , é declarado como:
IMO, esta é uma forma mais clara do que verificar na onCreate, e se encaixa melhor com o princípio de responsabilidade única.
fonte
No meu caso,
onRestoreInstanceState
foi chamado quando a atividade foi reconstruída após alterar a orientação do dispositivo.onCreate(Bundle)
foi chamado primeiro, mas o pacote não tinha a chave / valores que eu defini comonSaveInstanceState(Bundle)
.Em seguida,
onRestoreInstanceState(Bundle)
foi chamado com um pacote que continha as chaves / valores corretos.fonte
Acabei de me deparar com isso e percebi que a documentação tinha minha resposta:
"Esta função nunca será chamada com um estado nulo."
https://developer.android.com/reference/android/view/View.html#onRestoreInstanceState(android.os.Parcelable)
No meu caso, estava me perguntando por que onRestoreInstanceState não estava sendo chamado na instanciação inicial. Isso também significa que, se você não armazenar nada, ele não será chamado quando você reconstruir sua visualização.
fonte
Eu posso fazer assim (desculpe, c # não é java, mas não é um problema ...):
private int iValue = 1234567890; function void MyTest() { Intent oIntent = new Intent (this, typeof(Camera2Activity)); Bundle oBundle = new Bundle(); oBundle.PutInt("MYVALUE", iValue); //=> 1234567890 oIntent.PutExtras (oBundle); iRequestCode = 1111; StartActivityForResult (oIntent, 1111); }
E EM SUA ATIVIDADE PARA RESULTADO
private int iValue = 0; protected override void OnCreate(Bundle bundle) { Bundle oBundle = Intent.Extras; if (oBundle != null) { iValue = oBundle.GetInt("MYVALUE", 0); //=>1234567890 } } private void FinishActivity(bool bResult) { Intent oIntent = new Intent(); Bundle oBundle = new Bundle(); oBundle.PutInt("MYVALUE", iValue);//=>1234567890 oIntent.PutExtras(oBundle); if (bResult) { SetResult (Result.Ok, oIntent); } else SetResult(Result.Canceled, oIntent); GC.Collect(); Finish(); }
FINALMENTE
protected override void OnActivityResult(int iRequestCode, Android.App.Result oResultCode, Intent oIntent) { base.OnActivityResult (iRequestCode, oResultCode, oIntent); iValue = oIntent.Extras.GetInt("MYVALUE", -1); //=> 1234567890 }
fonte