重新向onResume上的片段添加视图会返回IllegalStateException

时间:2012-06-26 09:50:57

标签: android android-fragments

我正在开发带有片段的Android 3.1 Tablet应用程序。

我已经看到只有两个片段同时存在于内存中。当我显示第三个时,首先调用onDestroyView

我以编程方式将EditText添加到片段视图中。在EditText方法的片段视图重新创建之后,那些onResume不再显示。

我使用EditText来让用户向表单添加数据,然后在firstTable HashMap中存储引用。我将使用HashMap来检索用户的值。

在这里,我以编程方式创建EditText

private LinearLayout createNewFirstTableRow(long articleId)
{
    LinearLayout layout = new LinearLayout(mActivity);
    LayoutParams parentParams = new LayoutParams(LayoutParams.MATCH_PARENT, 40);
    parentParams.weight = 1;
    layout.setLayoutParams(parentParams);

    if (firstTable == null)
        firstTable = new HashMap<Long, ArrayList<EditText>>();

    ArrayList<EditText> fields = new ArrayList<EditText>(7);

    LayoutParams params = new LayoutParams(0, 40);
    params.weight = 0.125f;

    TextView textView = new TextView(mActivity);
    textView.setLayoutParams(params);
    textView.setText(new Long(articleId).toString());
    layout.addView(textView);

    for (int i = 0; i < 7; i++)
    {
        EditText edit = new EditText(mActivity);
        edit.setLayoutParams(params);
        edit.setInputType(InputType.TYPE_CLASS_NUMBER);
        fields.add(i, edit);
        layout.addView(edit);
    }

    firstTable.put(new Long(articleId), fields);

    return layout;
}

firstTable变量是一个全局变量:private HashMap<Long, ArrayList<EditText>> firstTable;

要添加EditText,请在onResume上执行以下操作:

@Override
public void onResume()
{
    Log.v("QuantityFragment", "onResume: " + firstTableRowIndex);

    if ((firstTable != null) && (secondTable != null))
    {
        firstTableRowIndex = FIRST_TABLE_ROW_INDEX;
        secondTableRowIndex = SECOND_TABLE_ROW_INDEX;

        LinearLayout table = (LinearLayout)view.findViewById(R.id.quantityTable);

        for (int index = 0; index < firstTable.size(); index++)
        {
            Long articleId = articleIds.get(index);

            table.addView(resumeTable(articleId, secondTable.get(articleId)), secondTableRowIndex);
            table.addView(resumeTable(articleId, firstTable.get(articleId)), firstTableRowIndex);

            firstTableRowIndex++;
            secondTableRowIndex++;
        }
    }

    super.onResume();
}

private LinearLayout resumeTable(Long articleId, ArrayList<EditText> fields)
{
    LinearLayout layout = new LinearLayout(mActivity);
    LayoutParams parentParams = new LayoutParams(LayoutParams.MATCH_PARENT, 40);
    parentParams.weight = 1;
    layout.setLayoutParams(parentParams);


    LayoutParams params = new LayoutParams(0, 40);
    params.weight = 0.125f;

    TextView textView = new TextView(mActivity);
    textView.setLayoutParams(params);
    textView.setText(new Long(articleId).toString());
    layout.addView(textView);

    for (int index = 0; index < fields.size(); index++)
    {
        layout.addView(fields.get(index));
    }

    return layout;
}

但是,layout.addView(textView);我得到一个例外:

IllegalStateException:指定的子级已有父级。您必须首先在孩子的父母上调用removeView()。

还有其他方法可以重新添加EditText吗?

更新

我已解决了更改resumeTable的问题:

private LinearLayout resumeTable(Long articleId, ArrayList<EditText> fields)
{
    LinearLayout layout = new LinearLayout(mActivity);
    LayoutParams parentParams = new LayoutParams(LayoutParams.MATCH_PARENT, 40);
    parentParams.weight = 1;
    layout.setLayoutParams(parentParams);


    LayoutParams params = new LayoutParams(0, 40);
    params.weight = 0.125f;

    TextView textView = new TextView(mActivity);
    textView.setLayoutParams(params);
    textView.setText(new Long(articleId).toString());
    layout.addView(textView);

    for (int index = 0; index < fields.size(); index++)
    {
        LinearLayout parent = (LinearLayout)fields.get(index).getParent();
        parent.removeView(fields.get(index));
        layout.addView(fields.get(index));
    }

    return layout;
}

这是重要的部分:

    for (int index = 0; index < fields.size(); index++)
    {
        LinearLayout parent = (LinearLayout)fields.get(index).getParent();
        parent.removeView(fields.get(index));
        layout.addView(fields.get(index));
    }

问题是开放的,如果您有更好的解决方案,请告诉我。

2 个答案:

答案 0 :(得分:2)

抛出该异常是因为您存储了对添加到布局中的ViewsEditText)的引用,之后您再次将这些Views重新添加到新版本中建造父母。

关于解决方案,我不知道为什么你决定存储对那些EditTexts的引用。我认为值得存储的唯一数据是EditTexts用户输入的文本,在这种情况下,您应该存储该文本而不是特定的EditText。您的方法将是:

//...
if (firstTable == null) {
    // your HashMap now stores text instead of an EditText
    firstTable = new HashMap<Long, ArrayList<String>>();// store only the text from the EditText
}

    ArrayList<String> fields = new ArrayList<String>(7);
    LayoutParams params = new LayoutParams(0, 40);
    params.weight = 0.125f;

    TextView textView = new TextView(mActivity);
    textView.setLayoutParams(params);
    textView.setText(new Long(articleId).toString());
    layout.addView(textView);

    for (int i = 0; i < 7; i++) {
        EditText edit = new EditText(mActivity);
        edit.setLayoutParams(params);
        edit.setInputType(InputType.TYPE_CLASS_NUMBER);
        fields.add(i, ""); // the EditText are empty at first
        layout.addView(edit);
    }
    firstTable.put(new Long(articleId), fields);

然后什么时候恢复EditTexts

private LinearLayout resumeTable(Long articleId, ArrayList<String> fields) {
    LinearLayout layout = new LinearLayout(mActivity);
    LayoutParams parentParams = new LayoutParams(LayoutParams.MATCH_PARENT, 40);
    parentParams.weight = 1;
    layout.setLayoutParams(parentParams);
    LayoutParams params = new LayoutParams(0, 40);
    params.weight = 0.125f;
    TextView textView = new TextView(mActivity);
    textView.setLayoutParams(params);
    textView.setText(new Long(articleId).toString());
    layout.addView(textView);
    for (int index = 0; index < fields.size(); index++) {
        // create new EditTexts
        EditText edit = new EditText(mActivity);
        edit.setLayoutParams(params);
        edit.setInputType(InputType.TYPE_CLASS_NUMBER);
        edit.setText(fields.get(index)); // get the text coresponding to this particular EditText
        layout.addView(edit);
    }
    return layout;
}

当然,当用户在EditTexts中输入内容时,您应将其存储在正确位置的firstTable变量中。

答案 1 :(得分:0)

我认为问题是由于两次添加字段元素

 ArrayList<EditText> fields = new ArrayList<EditText>(7);

1 - 在createNewFirstTableRow

for (int i = 0; i < 7; i++)
    {
        EditText edit = new EditText(mActivity);
        edit.setLayoutParams(params);
        edit.setInputType(InputType.TYPE_CLASS_NUMBER);
        fields.add(i, edit);//<-----------
        layout.addView(edit);//<----------- added in layout 
    }

2- onResume() - &gt; resumeTable

for (int index = 0; index < fields.size(); index++)
    {
        layout.addView(fields.get(index));//<----------------
    }

当在屏幕上添加字段元素alreay时,您无法添加两次.......