Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restoring view hierarchy from saved state does not restore views added programmatically

I am attempting to save and restore a view hierarchy consisting of a table of buttons. The number of table rows and buttons required in the table is not known until runtime, and are added programmatically to an inflated xml layout in my Activity's onCreate(Bundle) method. My question is: can the final table be saved and restored using Android's default view saving/restoring implementation?

An example of my current attempt is below. On the initial run, the table builds as expected. When the activity is destroyed (by rotating the device), the rebuilt view shows only an empty TableLayout with no children.

The xml file referenced in setContentView(int) includes, among other things, the empty TableLayout that the buttons are added to.

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

My understanding is that Android saves the state of views as long as they have an ID assigned to them, and restores the views when the activity is recreated, but right now it seems to reinflate the xml layout and nothing more. When debugging the code, I can confirm that onSaveInstanceState() is called on each Button in the table, but onRestoreInstanceState(Parcelable) is not.

like image 337
happydude Avatar asked Mar 15 '12 05:03

happydude


1 Answers

After searching through the source code for Activity, View and ViewGroup, I learned that the programmatically added views must be programmatically added and assigned the same ID each time onCreate(Bundle) is called. This is true regardless of whether it is creating the view for the first time, or recreating the view after destroying the activity. The saved instance state of the programmatically added views is then restored during the call to Activity.onRestoreInstanceState(Bundle). The easiest answer to the code above is simply to remove the check for 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);
   }
}
like image 158
happydude Avatar answered Oct 23 '22 10:10

happydude