2012-03-15 12 views
10

Próbuję zapisać i przywrócić hierarchię widoków składającą się z tabeli przycisków. Liczba wierszy i przycisków tabeli wymaganych w tabeli nie jest znana do czasu wykonania i są one programowo dodawane do zawyżonego układu xml w metodzie Activity z onCreate(Bundle). Moje pytanie brzmi: czy stół finałowy może zostać zapisany i odtworzony przy użyciu domyślnej implementacji zapisywania/odtwarzania widoku systemu Android?Przywracanie hierarchii widoków z zapisanego stanu nie powoduje przywracania widoków dodanych programowo

Przykład mojej obecnej próby znajduje się poniżej. Przy pierwszym uruchomieniu tabela jest zgodna z oczekiwaniami. Gdy działanie zostanie zniszczone (przez obrócenie urządzenia), przebudowany widok pokazuje tylko pusty TableLayout bez elementów podrzędnych.

Plik xml wymieniony w setContentView(int) zawiera, między innymi, pusty TableLayout, do którego dodawane są przyciski.

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    // Setup this activity's view. 
    setContentView(R.layout.game_board); 

    TableLayout table = (TableLayout) findViewById(R.id.table); 

    // If this is the first time building this view, programmatically 
    // add table rows and buttons. 
    if (savedInstanceState == null) { 
     int gridSize = 5; 
     // Create the table elements and add to the table. 
     int uniqueId = 1; 
     for (int i = 0; i < gridSize; i++) { 
      // Create table rows. 
      TableRow row = new TableRow(this); 
      row.setId(uniqueId++); 
      for (int j = 0; j < gridSize; j++) { 
       // Create buttons. 
       Button button = new Button(this); 
       button.setId(uniqueId++); 
       row.addView(button); 
      } 
      // Add row to the table. 
      table.addView(row); 
     } 
    } 
} 

moim rozumieniu jest to, że Android zapisuje stan poglądów, o ile mają one ID przypisane do nich, i przywraca poglądy, gdy działalność jest odtwarzany, ale teraz wydaje się reinflate układ xml i nic jeszcze. Podczas debugowania kodu mogę potwierdzić, że onSaveInstanceState() jest wywoływana na każdym Button w tabeli, ale nie jest to onRestoreInstanceState(Parcelable).

Odpowiedz

11

Po przeszukiwania kodu źródłowego Activity, View i ViewGroup, dowiedziałem się, że programowo dodane poglądy muszą być programowo dodane i przypisany ten sam identyfikator każdego czas jest wywoływany onCreate(Bundle). Jest to prawdą niezależnie od tego, czy tworzy widok po raz pierwszy, czy odtwarza widok po zniszczeniu działania. Zapisany stan instancji programowo dodanych widoków zostaje odtworzony podczas wywołania Activity.onRestoreInstanceState(Bundle). Najprostszą odpowiedzią na powyższy kod jest po prostu usunięcie testu dla savedInstanceState == null.

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    // Setup this activity's view. 
    setContentView(R.layout.game_board); 

    TableLayout table = (TableLayout) findViewById(R.id.table); 

    int gridSize = 5; 
    // Create the table elements and add to the table. 
    int uniqueId = 1; 
    for (int i = 0; i < gridSize; i++) { 
     // Create table rows. 
     TableRow row = new TableRow(this); 
     row.setId(uniqueId++); 
     for (int j = 0; j < gridSize; j++) { 
      // Create buttons. 
      Button button = new Button(this); 
      button.setId(uniqueId++); 
      row.addView(button); 
     } 
     // Add row to the table. 
     table.addView(row); 
    } 
} 
+3

To prawda: framework zapisuje i odtwarza stan każdego widoku, ale nie zapisuje, jakie widoki istnieją. Dlatego musisz wywołać 'setContentView()' niezależnie od tego, czy 'savedInstanceState' ma wartość null, i tak samo musisz utworzyć dowolne dynamiczne widoki wewnątrz' onCreate() '(lub' onCreateView() 'dla fragmentów). Zauważ, że jeśli dodasz widoki później (powiedzmy w 'onStart()'), to jest za późno, aby ich zawartość została przywrócona. –

+0

Więc zasadniczo, jeśli moja aktywność ma kilka widoków i fragmentów wygenerowanych przez interakcję z użytkownikiem, muszę zapamiętać każdy identyfikator, każdy widok i każdy typ Fragmentu? Jaki jest powód tego choce? Dlaczego po prostu nie przywracają wszystkiego tak, jak to było, gdy aplikacja została zabita? –

+0

Co się stanie, jeśli widoków nie można dodać podczas operacji onCreate? –

0

Linia ta odtwarza pusty układ:

setContentView(R.layout.game_board); 

Poza tym można przypisać równe identyfikatorów do wierszy i przycisków. Trzeba było stosować jeden licznik dla obu rzędów i przyciski:

int idCounter = 1; 
    for (int i = 0; i < gridSize; i++) { 
     TableRow row = new TableRow(this); 
     row.setId(idCounter++); 
     for (int j = 0; j < gridSize; j++) { 
      Button button = new Button(this); 
      button.setId(idCounter++); 
      row.addView(button); 
     } 
     ... 
    } 
+0

Dziękujemy za odpowiedź. Powyższy kod został zmodyfikowany, aby pokazać, że przypisanie unikalnego identyfikatora wszystkim programowo dodanym widokom daje taki sam wynik. Jak powinienem obsłużyć ustawienie widoku treści na pierwszym i kolejnych wywołaniach onCreate()? – happydude

Powiązane problemy