Como usar o exemplo onSavedInstanceState, por favor

110

Estou confuso quando se trata de salvar um estado. Então eu sei que onSaveInstanceState(Bundle)é chamado quando a atividade está prestes a ser destruída. Mas como armazenar suas informações nele e trazê-lo de volta ao seu estado original onCreate(Bundle savedInstanceState)? Não entendo como este pacote irá restaurar as informações. Seria útil se alguém pudesse dar um exemplo. O guia Dev não explica isso muito bem.

public class Conversation extends Activity {
    private ProgressDialog progDialog;
    int typeBar;
    TextView text1;
    EditText edit;
    Button respond;
    private String name;
    private String textAtView;
    private String savedName;

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        setContentView(R.layout.dorothydialog);
        text1 = (TextView)findViewById(R.id.dialog);
        edit = (EditText)findViewById(R.id.repsond);
        respond = (Button)findViewById(R.id.button01);

        if(savedInstanceState != null){
            savedInstanceState.get(savedName);
            text1.setText(savedName);
        }
        else{
            text1.setText("Hello! What is your name?");
            respond.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    name = edit.getText().toString();
                    text1.setText("Nice to meet you "+ name);
                }   
            });
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
        outState.putString(savedName, name);
    }
}
tj walker
fonte
text1.setText (savedInstanceState.getString (savedName));
Spidy
@Spidy E sobre onBackpressed? Como eu reagiria a isso com o pacote?
tj walker
Você não faria. Quando o usuário pressiona o botão Voltar. A atividade é eliminada. Use um banco de dados para armazenamento permanente de dados. Use o Bundle para retornar um aplicativo reiniciado ao seu estado anterior.
Spidy

Respostas:

198

O Bundleé um contêiner para todas as informações que você deseja salvar. Use as funções put * para inserir dados nele. Aqui está uma pequena lista (há mais) de funções put que você pode usar para armazenar dados no Bundle.

putString
putBoolean
putByte
putChar
putFloat
putLong
putShort
putParcelable (used for objects but they must implement Parcelable)

Em sua onCreatefunção, isso Bundleé devolvido ao programa. A melhor maneira de verificar se o aplicativo está sendo recarregado ou iniciado pela primeira vez é:

if (savedInstanceState != null) {
    // Then the application is being reloaded
}

Para obter os dados de volta, use as funções get * assim como as funções put *. Os dados são armazenados como um par nome-valor. É como um hashmap. Você fornece uma chave e o valor e, quando deseja o valor de volta, fornece a chave e a função obtém o valor. Aqui está um pequeno exemplo.

@Override
public void onSaveInstanceState(Bundle outState) {
   outState.putString("message", "This is my message to be reloaded");
   super.onSaveInstanceState(outState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        String message = savedInstanceState.getString("message");
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }
}

Sua mensagem salva será torrada na tela. Espero que isto ajude.

Spidy
fonte
14
onSaveInstanceState () é chamado antes que sua atividade seja pausada. Portanto, qualquer informação necessária após ser potencialmente destruída pode ser recuperada do Pacote salvo
Diederik
@Spidy Awesome! Você realmente me fez entender tudo sobre um pacote! então estou supondo que outState é passado de volta para o pacote savedInstanceState? Corrigir?
tj walker
Sim. O pacote outState é devolvido como o SavedInstanceState Bundle
Spidy
1
@tj walker - Outro grande recurso são os livros de referência técnica. Pro Android 3 é um recurso barato, mas extenso, que você pode obter na Amazon
Spidy
@Spidy Eu postei meu código de atividade acima para você ver. Talvez você possa me informar se estou salvando meu estado da maneira certa, como você sugeriu.
tj walker
34

Uma observação importante que todos os novos desenvolvedores Android devem saber é que qualquer informação em Widgets (TextView, Botões, etc.) será persistida automaticamente pelo Android, desde que você atribua um ID a eles. Isso significa que a maior parte do estado da interface do usuário é tratada sem problemas. Somente quando você precisa armazenar outros dados, isso se torna um problema.

Do Android Docs :

O único trabalho exigido por você é fornecer um ID exclusivo (com o atributo android: id) para cada widget cujo estado você deseja salvar. Se um widget não tiver um ID, ele não poderá salvar seu estado

Keith Adler
fonte
1
Bem, isso é realmente verdade? Porque eu tenho uma atividade com um botão para visualizar e editar texto. Se o aplicativo for destruído ou encerrado, tudo retornará ao seu estado original. No meu aplicativo, o texto textView muda toda vez que o usuário clica no botão.
tj walker
A documentação está incorreta? Nunca deixei uma View salvar suas próprias informações. Sua melhor aposta é salvar todas as suas informações por conta própria, na minha opinião.
Spidy
2
Se o seu objetivo é salvar informações, oSaveInstanceState NÃO é o lugar para fazê-lo. Isso ocorre porque não há garantia de que será chamado (consulte os documentos). Em vez disso, você deve gravar em um banco de dados, SharedPreferences, etc. Sim, esta informação é precisa. A melhor maneira de testar se sua IU está persistindo desta maneira é girar sua tela conforme as mudanças de orientação, execute novamente seu onCreate e use o pacote para restaurar o estado.
Keith Adler
@Nissan Fan, você pode dar um exemplo como o spidy fez acima? Com as preferências compartilhadas e tudo mais? Obrigado
tj walker
Os melhores exemplos vêm francamente da documentação. developer.android.com/guide/topics/data/data-storage.html#pref
Keith Adler
6

Uma boa informação: você não precisa verificar se o objeto Bundle é nulo no método onCreate (). Use o método onRestoreInstanceState (), que o sistema chama após o método onStart (). O sistema chama onRestoreInstanceState () apenas se houver um estado salvo para restaurar, então você não precisa verificar se o Bundle é nulo

Diego souza
fonte
5

Guardar informação:

static final String PLAYER_SCORE = "playerScore";
static final String PLAYER_LEVEL = "playerLevel";

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(PLAYER_SCORE, mCurrentScore);
    savedInstanceState.putInt(PLAYER_LEVEL, mCurrentLevel);

// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}

Se você não deseja restaurar informações em seu método onCreate:

Aqui estão os exemplos: Recriando uma atividade

Em vez de restaurar o estado durante onCreate (), você pode escolher implementar onRestoreInstanceState (), que o sistema chama após o método onStart (). O sistema chama onRestoreInstanceState () apenas se houver um estado salvo para restaurar, então você não precisa verificar se o Bundle é nulo

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
mCurrentScore = savedInstanceState.getInt(PLAYER_SCORE);
mCurrentLevel = savedInstanceState.getInt(PLAYER_LEVEL);
}
Klatschen
fonte
0

Basicamente, onSaveInstanceState (Bundle outBundle) lhe dará um bundle. Quando você olhar para a classe Bundle, verá que pode colocar muitas coisas diferentes dentro dela. Na próxima chamada de onCreate (), você apenas obterá esse Bundle de volta como um argumento. Então você pode ler seus valores novamente e restaurar sua atividade.

Digamos que você tenha uma atividade com um EditText. O usuário escreveu algum texto dentro dele. Depois disso, o sistema chama seu onSaveInstanceState (). Você lê o texto do EditText e o grava no Bundle por meio de Bundle.putString ("edit_text_value", theValue).

Agora onCreate é chamado. Você verifica se o pacote fornecido não é nulo. Se for esse o caso, você pode restaurar seu valor por meio de Bundle.getString ("edit_text_value") e colocá-lo de volta em seu EditText.


fonte
0

Isso é para informações extras.

Imagine este cenário

  1. ActivityA lança ActivityB.
  2. ActivityB lança um novo ActivityAPrime por

    Intent intent = new Intent(getApplicationContext(), ActivityA.class);
    startActivity(intent);
  3. ActivityAPrime não tem relacionamento com ActivityA.
    Nesse caso, o Bundle em ActivityAPrime.onCreate () será nulo.

Se ActivityA e ActivityAPrime devem ser a mesma atividade em vez de atividades diferentes, ActivityB deve chamar finish () em vez de startActivity ().

ken
fonte
apenas para esclarecer, em seu exemplo, é ActivityA == ActivityA instância 1 e ActivityAPrime == ActivityA instância 2? também, quando você diz, "ActivityB deve chamar finish () em vez de startActivity ()." você quer dizer: (1) AcitivityB deve chamar finish () e então usar startActivity () depois (2) ou ActivityB deve chamar finish () em vez de usar startActivity ()? se você quisesse dizer a opção 2, como você sugeriria que alguém reiniciasse a mesma atividadeA instância1 para que você possa carregar os dados contidos na atividade antes de ser destruída / concluída? Obrigado
cjayem13
ActivityA e ActivityAPrime são da mesma classe, mas instâncias diferentes. Neste cenário, a ActivityA ainda não finalizou seu negócio, no meio dele criou e iniciou a ActivityB, então quando a ActivityB terminar, a ActivityA deve continuar seu restante de negócios. É errado chamar startActivity neste caso e esperar que ActivityA e ActiviyAPrime sejam a mesma instância. portanto, não devemos reiniciar a ActivityA, apenas conclua a ActivityB e deixe a ActivityA retomar sua operação ...
ken
0

Se os dados não forem carregados de, savedInstanceStateuse o código a seguir.
O problema é que a chamada de url não deve ser totalmente concluída, portanto, verifique se os dados foram carregados e mostre o valor de instanceState.

//suppose data is not Loaded to savedInstanceState at 1st swipe
if (savedInstanceState == null && !mAlreadyLoaded){
    mAlreadyLoaded = true;
    GetStoryData();//Url Call
} else {
    if (listArray != null) {  //Data Array From JsonArray(ListArray)
        System.out.println("LocalData  " + listArray);
        view.findViewById(R.id.progressBar).setVisibility(View.GONE);
    }else{
        GetStoryData();//Url Call
    }
}
Mathan Chinna
fonte