Jak korzystać z przykładu onSavedInstanceState, proszę

110

Jestem zdezorientowany, jeśli chodzi o ratowanie stanu. Więc wiem, że onSaveInstanceState(Bundle)jest to wywołane, gdy działalność ma zostać zniszczona. Ale w jaki sposób przechowujesz w nim swoje informacje i przywracasz je do pierwotnego stanu onCreate(Bundle savedInstanceState)? Nie rozumiem, jak ten pakiet przywróci informacje. Byłoby pomocne, gdyby ktoś mógł podać przykład. Przewodnik dla programistów nie wyjaśnia tego dobrze.

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
źródło
text1.setText (saveInstanceState.getString (saveName));
Spidy
@Spidy A co z onBackpressed? Jak zareagowałbym na to z pakietem?
tj walker
Nie zrobiłbyś tego. Gdy użytkownik naciśnie przycisk Wstecz. Aktywność zostaje zabita. Użyj bazy danych do trwałego przechowywania danych. Użyj pakietu, aby przywrócić zrestartowaną aplikację do poprzedniego stanu.
Spidy

Odpowiedzi:

198

BundleJest pojemnik do wszystkich informacji, które chcesz zapisać. Używasz funkcji put *, aby wstawiać do niego dane. Oto krótka lista (jest ich więcej) funkcji put, których możesz użyć do przechowywania danych w Bundle.

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

W twojej onCreatefunkcji Bundlejest to zwracane do programu. Najlepszym sposobem sprawdzenia, czy aplikacja jest przeładowywana lub uruchamiana po raz pierwszy, jest:

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

Aby odzyskać dane, użyj funkcji get * tak samo jak funkcji put *. Dane są przechowywane jako para nazwa-wartość. To jest jak hasz. Podajesz klucz i wartość, a następnie, gdy chcesz odzyskać wartość, podajesz klucz, a funkcja pobiera wartość. Oto krótki przykład.

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

Twoja zapisana wiadomość zostanie wyświetlona na ekranie. Mam nadzieję że to pomoże.

Spidy
źródło
14
onSaveInstanceState () jest wywoływana przed wstrzymaniem działania. Więc wszelkie informacje, których potrzebuje po tym, jak zostanie potencjalnie zniszczone, można odzyskać z zapisanego pakietu
Diederik
@Spidy Awesome! Po prostu naprawdę sprawiłeś, że zrozumiałem wszystko o pakiecie! więc domyślam się, że outState jest przekazywana z powrotem do pakietu saveInstanceState? Poprawny?
tj walker
Tak. Pakiet outState zostaje przekazany z powrotem jako zapisany pakiet InstanceState
Spidy
1
@tj walker - Kolejnym świetnym źródłem są podręczniki techniczne. Pro Android 3 to tani, ale obszerny zasób, który można uzyskać na Amazon
Spidy
@Spidy Opublikowałem powyżej mój kod aktywności, abyś mógł zobaczyć. Może mógłbyś dać mi znać, czy dobrze ratuję mój stan, jak sugerowałeś.
tj walker
34

Jedną z głównych uwag, o których powinni wiedzieć wszyscy nowi programiści Androida, jest to, że wszelkie informacje w widżetach (TextView, przyciski itp.) Będą automatycznie utrwalane przez Androida, o ile przypiszesz im identyfikator. Oznacza to, że większość stanu interfejsu użytkownika jest obsługiwana bez problemu. Tylko wtedy, gdy musisz przechowywać inne dane, staje się to problemem.

Z Dokumentów na Androida :

Jedyną pracą wymaganą przez Ciebie jest podanie unikalnego identyfikatora (z atrybutem android: id) dla każdego widżetu, dla którego chcesz zapisać jego stan. Jeśli widget nie ma identyfikatora, nie może zapisać swojego stanu

Keith Adler
źródło
1
Czy to naprawdę prawda? Ponieważ mam aktywność z widokiem tekstu przycisku i edytuj tekst. Jeśli aplikacja zostanie zniszczona lub zabita, wszystko wraca do pierwotnego stanu. W mojej aplikacji teksty textView zmieniają się za każdym razem, gdy użytkownik kliknie przycisk.
tj walker
Czy dokumentacja jest niedokładna? Nigdy nie miałem widoku zapisującego własne informacje. Moim zdaniem najlepszym rozwiązaniem jest samodzielne zapisanie wszystkich informacji.
Spidy
2
Jeśli Twoim celem jest zapisywanie informacji w SaveInstanceState, NIE jest to miejsce do zrobienia tego. Dzieje się tak, ponieważ nie ma gwarancji, że zostanie wywołany (patrz dokumentacja). Zamiast tego powinieneś pisać do bazy danych, SharedPreferences itp. Tak, te informacje są dokładne. Najlepszym sposobem sprawdzenia, czy interfejs użytkownika utrzymuje się w ten sposób, jest obrócenie ekranu w miarę zmiany orientacji, ponowne uruchomienie onCreate i użycie pakietu do przywrócenia stanu.
Keith Adler
@Nissan Fan czy możesz podać przykład, jak zrobił to Spidy powyżej? Z udostępnionymi prefami i wszystkim? Dzięki
tj walker
Szczerze mówiąc, najlepsze przykłady pochodzą z dokumentacji. developer.android.com/guide/topics/data/data-storage.html#pref
Keith Adler
6

Dobra informacja: nie musisz sprawdzać, czy obiekt Bundle ma wartość null w metodzie onCreate (). Należy użyć metody onRestoreInstanceState (), którą system wywołuje po metodzie onStart (). System wywołuje metodę onRestoreInstanceState () tylko wtedy, gdy istnieje zapisany stan do przywrócenia, więc nie ma potrzeby sprawdzania, czy pakiet jest pusty

Diego Souza
źródło
5

Przechowaj informację:

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

Jeśli nie chcesz przywracać informacji w metodzie onCreate:

Oto przykłady: Odtwarzanie działania

Zamiast przywracania stanu podczas onCreate () możesz zdecydować się na implementację onRestoreInstanceState (), którą system wywołuje po metodzie onStart (). System wywołuje metodę onRestoreInstanceState () tylko wtedy, gdy istnieje zapisany stan do przywrócenia, więc nie ma potrzeby sprawdzania, czy pakiet jest pusty

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
źródło
0

Zasadniczo onSaveInstanceState (Bundle outBundle) da ci pakiet. Kiedy spojrzysz na klasę Bundle, zobaczysz, że możesz włożyć do niej wiele różnych rzeczy. Przy następnym wywołaniu onCreate () po prostu otrzymujesz ten pakiet jako argument. Następnie możesz ponownie odczytać swoje wartości i przywrócić swoją aktywność.

Powiedzmy, że masz działanie z EditTextem. Użytkownik napisał w nim jakiś tekst. Następnie system wywołuje metodę onSaveInstanceState (). Czytasz tekst z EditText i zapisujesz go w pakiecie poprzez Bundle.putString ("edit_text_value", theValue).

Teraz nazywa się onCreate. Sprawdzasz, czy dostarczony pakiet nie jest zerowy. W takim przypadku możesz przywrócić swoją wartość poprzez Bundle.getString ("edit_text_value") i umieścić ją z powrotem w EditText.


źródło
0

To jest dla dodatkowych informacji.

Wyobraź sobie taki scenariusz

  1. Aktywność A Uruchomienie Aktywność B.
  2. ActivityB uruchom nowy ActivityAPrime przez

    Intent intent = new Intent(getApplicationContext(), ActivityA.class);
    startActivity(intent);
    
  3. ActivityAPrime nie ma związku z ActivityA.
    W tym przypadku pakiet w ActivityAPrime.onCreate () będzie miał wartość NULL.

Jeśli ActivityA i ActivityAPrime powinny być tym samym działaniem, a nie różnymi działaniami, ActivityB powinno wywołać finish () niż użycie startActivity ().

rozpoznać
źródło
żeby wyjaśnić, w twoim przykładzie, jest ActivityA == ActivityA instancja 1 i ActivityAPrime == ActivityA instancja 2? również, gdy mówisz, „ActivityB powinno wywołać finish () niż użycie startActivity ()”. czy masz na myśli: (1) AcitivityB powinno wywołać finish (), a następnie użyć startActivity () afterwards (2), czy też ActivityB powinno wywołać finish () zamiast w ogóle używać startActivity ()? gdybyś miał na myśli opcję 2, w jaki sposób zasugerowałbyś komuś ponowne uruchomienie tej samej czynności A instance1, abyś mógł załadować dane, które zawierała aktywność przed zniszczeniem / zakończeniem? Dzięki
cjayem13
ActivityA i ActivityAPrime są tej samej klasy, ale w różnych instancjach. W tym scenariuszu Działanie A nie zakończyło jeszcze swojej działalności, w środku utworzyło i uruchomiło Działanie B, więc po zakończeniu Działania B, Działanie A powinno kontynuować pozostałą część działalności. Błędem jest wywoływanie startActivity w tym przypadku i oczekiwanie, że ActivityA i ActiviyAPrime będą tą samą instancją. więc nie powinniśmy ponownie uruchamiać Aktywności A, po prostu kończyć Aktywność B i pozwolić Aktywności A wznowić jej działanie ...
ken
0

Jeśli dane nie są ładowane z, savedInstanceStateużyj następującego kodu.
Problem polega na tym, że wywołanie adresu URL nie jest w pełni zakończone, więc sprawdź, czy dane są załadowane, a następnie pokaż wartość 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
źródło