【问题标题】:Restoring view hierarchy from saved state does not restore views added programmatically从保存状态恢复视图层次结构不会恢复以编程方式添加的视图
【发布时间】:2012-03-31 15:19:19
【问题描述】:

我正在尝试保存和恢复由按钮表组成的视图层次结构。表格中所需的表格行数和按钮数直到运行时才知道,并且在我的ActivityonCreate(Bundle) 方法中以编程方式添加到膨胀的xml 布局中。我的问题是:可以使用Android的默认视图保存/恢复实现来保存和恢复决赛桌吗?

下面是我当前尝试的一个示例。在初始运行时,表按预期构建。当 Activity 被销毁(通过旋转设备)时,重建后的视图只显示一个空的 TableLayout,没有子节点。

setContentView(int) 中引用的 xml 文件包括添加按钮的空 TableLayout

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

我的理解是,只要为视图分配了 ID,Android 就会保存视图的状态,并在重新创建 Activity 时恢复视图,但现在它似乎重新膨胀了 xml 布局,仅此而已。在调试代码时,我可以确认在表中的每个Button 上都调用了onSaveInstanceState(),但onRestoreInstanceState(Parcelable) 没有。

【问题讨论】:

    标签: android layout view


    【解决方案1】:

    在搜索ActivityViewViewGroup的源代码后,我了解到每次调用onCreate(Bundle)时,必须以编程方式添加并分配相同的ID。无论是第一次创建视图,还是在销毁活动后重新创建视图,都是如此。然后在调用Activity.onRestoreInstanceState(Bundle) 期间恢复以编程方式添加的视图的已保存实例状态。上面代码最简单的答案就是去掉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);
       }
    }
    

    【讨论】:

    • 没错:框架保存和恢复每个视图的状态,但它不保存存在哪些视图。这就是为什么无论savedInstanceState 是否为空,您都必须调用setContentView(),并且您必须自己在onCreate()(或onCreateView() 用于片段)中创建任何动态视图。请注意,如果您稍后添加视图(例如,在 onStart() 中),则为时已晚,无法恢复其内容。
    • 所以基本上,如果我的 Activity 有多个通过用户交互生成的视图和片段,我需要记住每个 ID、每个视图和每种类型的 Fragment?这个选择的原因是什么?他们为什么不简单地恢复应用程序被杀死时的一切?
    • onCreate时无法添加视图怎么办?
    • @AntonioSesto 很好的解释。只有我想更正在 onStart() 之后恢复视图状态。然后在那里创建视图是安全的(developer.android.com/reference/android/app/…)当它不安全时。
    【解决方案2】:

    这一行重新创建了一个空布局:

    setContentView(R.layout.game_board);
    

    此外,您可以为行和按钮分配相同的 id。您应该对行和按钮都使用一个计数器:

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

    【讨论】:

    • 感谢您的回复,上面的代码已经过编辑,以显示为所有以编程方式添加的视图分配唯一 ID 具有相同的结果。我应该如何处理在第一次和后续 onCreate() 调用中设置内容视图?
    【解决方案3】:

    如果它适用于带有 ID 的视图,为什么不在创建表格时为每个按钮指定一个 ID?看看这是否有效。

    How can I assign an ID to a view programmatically?

    【讨论】:

    • 请查看上面的代码,所有行和按钮都已经以编程方式添加了 ID。
    猜你喜欢
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    • 2017-01-04
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-26
    相关资源
    最近更新 更多