2012-03-15 6 views
10

Estoy intentando guardar y restaurar una jerarquía de vista que consiste en una tabla de botones. El número de filas de tablas y botones necesarios en la tabla no se conoce hasta el tiempo de ejecución, y se agregan mediante programación a un diseño xml inflado en el método ActivityonCreate(Bundle). Mi pregunta es: ¿la mesa final se puede guardar y restaurar usando la vista predeterminada de Android para guardar/restaurar la implementación?Restaurar la jerarquía de vista desde el estado guardado no restaura las vistas agregadas de forma programática

A continuación, se incluye un ejemplo de mi intento actual. En la ejecución inicial, la tabla se construye como se esperaba. Cuando se destruye la actividad (girando el dispositivo), la vista reconstruida muestra solo un TableLayout vacío sin hijos.

El archivo xml al que se hace referencia en setContentView(int) incluye, entre otras cosas, el TableLayout vacío al que se agregan los botones.

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

Mi entendimiento es que Android guarda el estado de puntos de vista, siempre y cuando tengan un ID asignado a ellos, y restaura los puntos de vista cuando se recrea la actividad, pero ahora parece volver a inflar el diseño xml y nada Más. Al depurar el código, puedo confirmar que se llama a onSaveInstanceState() en cada Button en la tabla, pero no a onRestoreInstanceState(Parcelable).

Respuesta

11

Después de buscar en el código fuente de Activity, View y ViewGroup, supe que los puntos de vista agregado mediante programación se deben agregar mediante programación y se les asigna el mismo ID de cada uno se llama el tiempo onCreate(Bundle). Esto es cierto independientemente de si está creando la vista por primera vez o recreando la vista después de destruir la actividad. El estado de la instancia guardada de las vistas agregadas mediante programación se restaura luego durante la llamada al Activity.onRestoreInstanceState(Bundle). La respuesta más sencilla al código anterior es simplemente eliminar el cheque de 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

Correcto: el marco guarda y restaura el estado de cada vista, pero no guarda qué vistas existen. Es por eso que tienes que llamar a 'setContentView()' independientemente de si 'savedInstanceState' es nulo, y de la misma manera tienes que crear cualquier vista dinámica dentro de' onCreate() '(o' onCreateView() 'para los fragmentos). Tenga en cuenta que si agrega vistas más adelante (por ejemplo, en 'onStart()'), es demasiado tarde para que se restauren sus contenidos. –

+0

Entonces, básicamente, si mi Actividad tiene varias vistas y fragmentos generados a través de la interacción del usuario, ¿necesito recordar cada ID, cada vista y cada tipo de Fragmento? ¿Cuál es el motivo de esta choce? ¿Por qué no simplemente restablecen todo como era cuando la aplicación fue asesinada? –

+0

¿Qué pasa si las vistas no se pueden agregar durante onCreate? –

0

Si funciona con vistas con una identificación, ¿por qué no le das a cada botón una identificación en la tabla cuando las estás creando? Ve si eso funciona.

How can I assign an ID to a view programmatically?

+1

Revise el código anterior, todas las filas y botones ya tienen identificaciones añadidas programáticamente. – happydude

0

Esta línea recrea una composición vacía:

setContentView(R.layout.game_board); 

Además, se asigna de id iguales a las filas y botones. Que debería haber utilizado un contador de las filas y botones:

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

Gracias por la respuesta, el código anterior se ha editado para mostrar que la asignación de una ID única a todas las vistas agregadas mediante programación tiene el mismo resultado. ¿Cómo debo manejar la configuración de la vista de contenido en la primera y posteriores llamadas a Create()? – happydude

Cuestiones relacionadas