Android动态表布局-添加视图引发异常IllegalStateException(子级已经有父级)

Android动态表布局-添加视图引发异常IllegalStateException(子级已经有父级),android,android-layout,android-view,Android,Android Layout,Android View,在Java中创建一个布局作为所需的TableLayouts的数量,这不称为designtime 调用createPlayerTables() 当我尝试将ImageView列表中的ImageView添加到第一个TableRow时,在循环的第一行引发异常: for (int i = 0; i < 3; i++) { tableRowsLst.get(0).addView((ImageView) imageViewsLst.get(i)); tableRowsLst.get(1)

在Java中创建一个布局作为所需的TableLayouts的数量,这不称为designtime

调用
createPlayerTables()

当我尝试将ImageView列表中的ImageView添加到第一个TableRow时,在循环的第一行引发异常:

for (int i = 0; i < 3; i++) {
    tableRowsLst.get(0).addView((ImageView) imageViewsLst.get(i));
    tableRowsLst.get(1).addView((ImageView) imageViewsLst.get(i+3));
}
for(int i=0;i<3;i++){
tableRowsList.get(0).addView((ImageView)ImageViewsList.get(i));
tableRowsList.get(1.addView)((ImageView)ImageViewsList.get(i+3));
}
该错误表明ImageView已添加到视图组中,但看到下面的代码,我创建了新的ImageView,并且只将它们添加到它出错的行中的视图组中,因此我不确定为什么失败

// List<ImageView> imageViewsLst = new ...
// List<TableRow> tableRowsLst = new ...

/**
* Initialises the TableLayouts, one per player
*/ 
private TableLayout createPlayerTables(int playerNum) {
    ...

    for (int i = 0; i < 6; i++) {
        imageViewsLst.add(new ImageView(this));
        ...
    }

    for (int i = 0; i < 3; i++) {
        tableRowsLst.add(new TableRow(this));
        ...
    }

    for (int i = 0; i < 3; i++) {
        tableRowsLst.get(0).addView((ImageView) imageViewsLst.get(i));
        tableRowsLst.get(1).addView((ImageView) imageViewsLst.get(i+3));
    }

    ...
}
//列表imageViewsLst=new。。。
//列表表ROWSLST=新建。。。
/**
*初始化表格布局,每个玩家一个
*/ 
专用表布局createPlayerTables(int-playerNum){
...
对于(int i=0;i<6;i++){
ImageViewsList.add(新建ImageView(此));
...
}
对于(int i=0;i<3;i++){
tableRowsList.add(新TableRow(this));
...
}
对于(int i=0;i<3;i++){
tableRowsList.get(0).addView((ImageView)ImageViewsList.get(i));
tableRowsList.get(1.addView)((ImageView)ImageViewsList.get(i+3));
}
...
}

啊哈!好吧,在几次错误的开始之后,问题来了

imageViewsList
是一个成员变量。每次调用createPlayerTables时都会添加6个视图,然后每次都使用前6个视图。第一次传球(球员0),没问题。第二次传球(球员1):轰

选项1)不保存它们。给定的代码不需要它们,尽管这并不能覆盖所有的基础。你可以把它们从桌上的几行中挖出来,在必要时扔掉

选项2)通过
playerNum*6
偏移对imageViewsList的访问权限(当第一次调用
createPlayerTables()
时,
==imageViewsList.size()

友好的建议:您可以通过两种不同的方式发现问题:

  • 在每次调用TableRow.add()之前使用对象ID的Log.d()将显示第二次传递中使用的相同对象ID,紧接着是异常
  • 在方便的Dandy调试器中逐步完成代码。是的,这有很多代码需要一步一步来找出在这种情况下发生了什么。使用两个不同的断点可以更容易地查看对createPlayerTables()的调用正在抛出,并允许您仅在cpt()即将抛出时才进入cpt()
每次发现一个bug时,都要问自己“我能做些什么来捕捉这个错误”,这将极大地提高您的调试技能。

在这个循环中:

for (int i = 0; i < 3; i++){
   tableRowsLst.add(new TableRow(this));
   tableRowsLst.get(i).setLayoutParams(
       new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, dipToPixels(55)));
   tableRowsLst.get(i).setOrientation(LinearLayout.HORIZONTAL);
}

虽然在本例中并非如此,但此问题的另一个常见原因是未正确使用
onCreateDialog()
onPrepareDialog()
。只调用一次
onCreateDialog()
,此处所做的任何操作都将保持不变。如果要将动态内容添加到版面
(对话框)
,则可能需要使用
onPrepareDialog()
,这将在创建之后但在每次显示之前发生。引自:

在显示对话框之前,Android还调用可选的回调方法onPrepareDialog(int,dialog)。如果要在每次打开对话框时更改其任何属性,请定义此方法。此方法在每次打开对话框时调用,而onCreateDialog(int)仅在第一次打开对话框时调用。如果未定义onPrepareDialog(),则对话框将与上次打开时保持不变。此方法还会传递对话框的ID以及在onCreateDialog()中创建的对话框对象


我只使用了前三个元素,因为我认为在将行添加到tablelayout之后,可以重用元素;指定new时,我认为我没有重用相同的视图:将新TableRow保存到元素(就像我做的那样)和首先清除它有什么区别?我在这个arraylist和ImageViewsList中添加了一个clear,因为同样的问题也发生在这里(感谢Mark的提醒和建议):)谢谢大家的帮助:DYou没有。您创建了新的列表并将它们添加到相同的
表rowslt
。在第二次运行时,它包含6个元素,然后是9个。。。然后,您尝试将它们全部添加到视图中,该视图抱怨说,因为其中一些已在之前添加。不好意思地咧嘴一笑,感谢您的重新解释!:我理解,但很多谷歌搜索者在查找“孩子已经有了父母”错误时(就像我所做的那样)会找到这个页面。+1是最后一行。这有助于:)
tableRowsLst.clear();