Come usare l'esempio di onSavedInstanceState per favore


110

Sono confuso quando si tratta di salvare uno stato. Quindi so che onSaveInstanceState(Bundle)viene chiamato quando l'attività sta per essere distrutta. Ma come immagazzini le tue informazioni e riportale al suo stato originale in onCreate(Bundle savedInstanceState)? Non capisco come questo pacchetto ripristinerà le informazioni. Sarebbe utile se qualcuno potesse fornire un esempio. La guida degli sviluppatori non fa un buon lavoro nello spiegare questo.

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);
    }
}

text1.setText (savedInstanceState.getString (savedName));
Spidy

@Spidy E per quanto riguarda onBackpressed? Come reagirei a questo con il bundle?
tj walker

Non lo faresti. Quando l'utente preme il pulsante Indietro. L'attività viene interrotta. Utilizzare un database per l'archiviazione permanente dei dati. Usa il bundle per riportare un'applicazione riavviata al suo stato precedente.
Spidy

Risposte:


198

Il Bundleè un contenitore di tutte le informazioni che si desidera salvare. Si utilizzano le funzioni put * per inserire dati al suo interno. Di seguito è riportato un breve elenco (ce ne sono altri) di funzioni put che puoi utilizzare per memorizzare i dati nel file Bundle.

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

Nella tua onCreatefunzione, questo Bundleviene restituito al programma. Il modo migliore per verificare se l'applicazione viene ricaricata o avviata per la prima volta è:

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

Per recuperare i dati, usa le funzioni get * proprio come le funzioni put *. I dati vengono archiviati come coppia nome-valore. È come una hashmap. Fornisci una chiave e il valore, quindi quando desideri restituire il valore, dai la chiave e la funzione ottiene il valore. Ecco un breve esempio.

@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();
    }
}

Il tuo messaggio salvato verrà tostato sullo schermo. Spero che questo ti aiuti.


14
onSaveInstanceState () viene chiamato prima che l'attività venga sospesa. Quindi qualsiasi informazione di cui ha bisogno dopo che è stata potenzialmente distrutta può essere recuperata dal Bundle salvato
Diederik,

@Spidy Awesome! Mi hai fatto capire davvero tutto di un pacchetto! quindi immagino che outState sia passato di nuovo al bundle savedInstanceState? Corretta?
tj walker

Sì. Il pacchetto outState viene restituito come pacchetto
savedInstanceState

1
@tj walker - Un'altra grande risorsa sono i libri di riferimento tecnico. Pro Android 3 è una risorsa economica ma ampia che puoi ottenere su Amazon
Spidy

@Spidy Ho pubblicato il mio codice attività sopra per farti vedere. Forse puoi farmi sapere se sto salvando il mio stato nel modo giusto, come hai suggerito.
tj walker

34

Una nota importante che tutti i nuovi sviluppatori Android dovrebbero sapere è che qualsiasi informazione in Widget (TextView, Buttons, ecc.) Verrà mantenuta automaticamente da Android fintanto che si assegna loro un ID. Quindi ciò significa che la maggior parte dello stato dell'interfaccia utente viene gestita senza problemi. Solo quando è necessario memorizzare altri dati questo diventa un problema.

Da Documenti Android :

L'unico lavoro richiesto da te è fornire un ID univoco (con l'attributo android: id) per ogni widget di cui desideri salvare il suo stato. Se un widget non ha un ID, non può salvare il suo stato


1
È proprio vero? Perché ho un'attività con un pulsante di visualizzazione del testo e modifica del testo. Se l'applicazione viene distrutta o uccisa, tutto viene riportato allo stato originale. Nella mia applicazione i testi textView cambiano ogni volta che l'utente fa clic sul pulsante.
tj walker

La documentazione è imprecisa? Non ho mai avuto una vista che salvi le proprie informazioni. La soluzione migliore è salvare tu stesso tutte le tue informazioni, secondo me.
Spidy

2
Se il tuo obiettivo è salvare le informazioni su SaveInstanceState, NON è il posto giusto per farlo. Questo perché non vi è alcuna garanzia che venga chiamato (vedere la documentazione). Dovresti invece scrivere su un database, SharedPreferences, ecc. Sì, queste informazioni sono accurate. Il modo migliore per verificare se la tua interfaccia utente persiste in questo modo è ruotare il display mentre i cambiamenti di orientamento rieseguono onCreate e usa il bundle per ripristinare lo stato.
Keith Adler

@Nissan Fan puoi fare un esempio come ha fatto Spidy sopra? Con le sharedprefs e tutto il resto? Grazie
tj walker

I migliori esempi provengono francamente dalla documentazione. developer.android.com/guide/topics/data/data-storage.html#pref
Keith Adler,

6

Una buona informazione: non è necessario controllare se l'oggetto Bundle è nullo nel metodo onCreate (). Utilizzare il metodo onRestoreInstanceState (), che il sistema chiama dopo il metodo onStart (). Il sistema chiama onRestoreInstanceState () solo se c'è uno stato salvato da ripristinare, quindi non è necessario controllare se il Bundle è nullo


5

Informazione di negozio:

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 non desideri ripristinare le informazioni nel tuo metodo onCreate:

Ecco gli esempi: Ricreazione di un'attività

Invece di ripristinare lo stato durante onCreate (), puoi scegliere di implementare onRestoreInstanceState (), che il sistema chiama dopo il metodo onStart (). Il sistema chiama onRestoreInstanceState () solo se c'è uno stato salvato da ripristinare, quindi non è necessario controllare se il Bundle è nullo

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);
}

0

Fondamentalmente onSaveInstanceState (Bundle outBundle) ti darà un bundle. Quando guardi la classe Bundle, vedrai che puoi inserire molte cose diverse al suo interno. Alla successiva chiamata di onCreate (), ottieni semplicemente quel Bundle come argomento. Quindi puoi leggere di nuovo i tuoi valori e ripristinare la tua attività.

Supponiamo che tu abbia un'attività con un EditText. L'utente ha scritto del testo al suo interno. Dopodiché il sistema chiama il tuo onSaveInstanceState (). Leggi il testo da EditText e lo scrivi nel Bundle tramite Bundle.putString ("edit_text_value", theValue).

Ora si chiama onCreate. Controlla se il bundle fornito non è nullo. In tal caso, puoi ripristinare il valore tramite Bundle.getString ("edit_text_value") e rimetterlo nel tuo EditText.


0

Questo è per informazioni aggiuntive.

Immagina questo scenario

  1. ActivityA lancia ActivityB.
  2. ActivityB lancia un nuovo ActivityAPrime di

    Intent intent = new Intent(getApplicationContext(), ActivityA.class);
    startActivity(intent);
  3. ActivityAPrime non ha alcuna relazione con ActivityA.
    In questo caso il bundle in ActivityAPrime.onCreate () sarà nullo.

Se ActivityA e ActivityAPrime dovrebbero essere la stessa attività invece di attività diverse, ActivityB dovrebbe chiamare finish () piuttosto che usare startActivity ().


solo per chiarire, nel tuo esempio, ActivityA == ActivityA istanza 1 e ActivityAPrime == ActivityA istanza 2? inoltre, quando dici "ActivityB dovrebbe chiamare finish () piuttosto che usare startActivity ()." vuoi dire: (1) AcitivityB dovrebbe chiamare finish () e quindi usare startActivity () in seguito (2) o ActivityB dovrebbe chiamare finish () invece di usare startActivity ()? se intendevi l'opzione 2, come suggeriresti a qualcuno di riavviare la stessa attivitàA istanza1 in modo da poter caricare i dati dell'attività contenuta prima di essere distrutta / terminata? Grazie
cjayem13

ActivityA e ActivityAPrime sono della stessa classe ma istanze diverse. In questo scenario, ActivityA non ha ancora terminato la sua attività, nel mezzo di essa, ha creato e avviato ActivityB, quindi quando ActivityB finisce, ActivityA dovrebbe continuare la sua attività rimanente. È sbagliato chiamare startActivity in questo caso e aspettarsi che ActivityA e ActiviyAPrime siano la stessa istanza. quindi non dovremmo riavviare ActivityA, basta finire ActivityB e lasciare che ActivityA riprenda la sua operazione ...
ken

0

Se i dati non vengono caricati da savedInstanceStateutilizzare il codice seguente.
Il problema è che la chiamata all'URL non deve essere completata completamente, quindi controlla se i dati sono caricati per mostrare il valore 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
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.