6

Ursprünglich ich diesen Fehler hätte:Widersprüchliche Android-Fehlermeldungen: Das angegebene Kind hat bereits einen Elternteil. Sie müssen rufen RemoveView() auf den Eltern Kind erst

The specified child already has a parent. You must call removeView() on the child's parent first

bei

customSection.addView(customLayout); 

So habe ich

((LinearLayout)customLayout.getParent()).removeView(customLayout); 

und bekommen

java.lang.NullPointerException 

Wenn also das Kind ein Elternteil hat und ich zuerst das Kind vom Elternteil entfernen muss, warum gibt getParent() null zurück?

Ich habe ein abstraktes Fragment, das abgeleiteten Klassen erlaubt, ein benutzerdefiniertes Layout für den Listenadapter zu liefern. Relevante Code:

Bindung:

public void bind(DataObject row) { 
    View customLayout = getChildItemView(row); 
    if (customLayout != null) { 
     ((LinearLayout) customLayout.getParent()).removeView(customLayout); 
     customSection.removeAllViews(); 
     customSection.addView(customLayout); 
     customSection.setVisibility(View.VISIBLE); 
    } else { 
     customLayout.setVisibility(View.INVISIBLE); 
    } 

} 

protected View getChildItemView(CommonRow row) { 
    if (parentView == null) { 
     parentView = (LinearLayout) LayoutInflater.from(getActivity()) 
       .inflate(R.layout.list_item_custom_section, 
         new LinearLayout(getActivity()), true); 
     label = (TextView) parentView.findViewById(R.id.txtData1Label); 
     value = (TextView) parentView.findViewById(R.id.txtData1Value); 
    } 
    label.setText("Minimum"); 
    value.setText(manager.formatMoney(((SpecificDataRow) row).minimum)); 
    return parentView; 
} 

Ich habe auch versucht inflater.inflate(R.layout.list_item_custom_section, null) ... falsch, null/false, was ist passiert?

EDIT:

@allprog, wusste ich, einige Bereinigung nötig war. Ich schrieb das am Ende des Tages etwas in Eile. Ich habe seitdem den Code aufgeräumt und die Bindung getrennt und die Ansicht aufgepumpt. Aufgeräumt Code:

private class ViewHolder { 
.... 

     public ViewHolder(View v) { 
      Butterknife.inject(this, v); 
      View custom = createCustomView(customSection); 
      if (custom != null) { 
       customSection.setVisibility(View.VISIBLE); 
       customSection.addView(custom); 
      } 
     } 

     public void bind(CommonRow row) { 
      ...... 

      bindCustomView(row, customSection); 
     } 

} 

Kinderklasse:

@Override 
    protected View createCustomView(ViewGroup parent) { 
     return LayoutInflater.from(getActivity()).inflate(R.layout.list_item_custom_section, parent, false); 
    } 


    @Override 
    protected void bindCustomView(CommonRow row, ViewGroup section) { 
     TextView label = Views.findById(section, R.id.txtData1Label); 
     TextView value = Views.findById(section, R.id.txtData1Value); 

     label.setText("Minimum"); 
     value.setText(manager.formatMoney(((SpecificRow) row).minimum)); 
    } 

suitianshi es wurde zuerst mit meinem ursprünglichen [ungepflegt] Code, der die Lösung war.

+1

Was ist 'customSection'? Können Sie den Code anzeigen, in dem er zuerst initialisiert wird? –

+0

Sie befindet sich in der getChildItemView-Methode (CommonRow-Zeile). parentView = (LinearLayout) LayoutInflater.from (getActivity()). inflate (R.layout.list_item_custom_section, neues LinearLayout (getActivity()), true); – Jack

+0

Können Sie das XML für list_item_custom_section posten? Ich vermute, dass Sie versuchen, die Ansicht zu sich selbst hinzuzufügen. Außerdem müsste die Variable "customSection" immer noch deklariert (und gesetzt) ​​werden. Kannst du diesen Code posten? –

Antwort

12

versuchen Sie dies:

public void bind(DataObject row) { 
    View customLayout = getChildItemView(row); 
    if (customLayout != null) { 
     if(customLayout.getParent() != null) { 
      ((LinearLayout)customLayout.getParent()).removeView(customLayout); 
     } 

     customSection.removeAllViews(); 
     customSection.addView(customLayout); 
     customSection.setVisibility(View.VISIBLE); 
    } else { 
     customLayout.setVisibility(View.INVISIBLE); 
    } 

} 

I zugehörige Quellcode gelesen haben, getParent sollten Nicht-Null-Wert zurück, wenn view ein Elternteil hat. Sie sollten stellen Sie sicher, es hat tatsächlich einen Elternteil vor dem Gießen und Rufen removeView

Wunsch dies hilft.

Quellcode:

in View:

public final ViewParent getParent() { 
     return mParent; 
    } 

in ViewGroup.addViewInner

if (child.getParent() != null) { 
    throw new IllegalStateException("The specified child already has a parent. " + 
     "You must call removeView() on the child's parent first."); 
} 
+0

Ich verstehe diesen Teil, das Problem ist, dass customSection.addView (customLayout) mit dem Fehler in OP-Titel fehlschlägt. So kann ich den ganzen Tag auf Null prüfen, aber es hilft mir immer noch nicht, das customLayout von seinem ursprünglichen [apparently null] Elternteil zu entfernen. Für mich ergibt das keinen Sinn. – Jack

+0

Quellcode zu meiner Antwort hinzugefügt. Du meinst, du bekommst diese Ausnahme, aber "getParent" reuturns null? das ist wirklich seltsam! – suitianshi

+0

und haben Sie versucht, 'ViewParent' an' ViewGroup' anstatt an 'LinearLayout' zu übertragen? – suitianshi

2

Wie ich Ihre parentView ist eine Feldvariable sehen können, ist dies der Schlüssel. Also, was ich vermute, wirklich vor sich geht:

Erster Aufruf von bind(): Sie parentView zu schaffen, und es ist noch kein Elternteil noch funktioniert gut, aber nachdem Sie einen Scheck für Eltern hinzugefügt scheitert es hier.

Zweiter Anruf von bind(): parentView ist jetzt ein Elternteil und Ihre hinzugefügte Überprüfung sollte jetzt funktionieren, aber Sie scheiterten im vorherigen Schritt. Ohne einen Scheck scheitern Sie hier mit Ausnahme im Titel.

Lösung: Überprüfen Sie das Vorhandensein von Eltern und entfernen Sie es nur, wenn es notwendig ist.

0

Zunächst gibt die LayoutInflate-Methode zum Aufblasen immer die Ansicht ohne Eltern zurück.

wenn attachToRoot == true wird die parentView dass new LinearLayout(getActivity())

wenn attachToRoot == false wird die parentViewR.layout.list_item_custom_section aufgeblasen werden, was auch immer es ist.

in beide Fälle die ((LinearLayout) customLayout.getParent()) wird null sein. Deshalb erhalten Sie NullPointerException. Sie können es in Return-Anweisung in LayoutInflater documentation sehen.

Wie oben erklärt parentView als Feld geschrieben wird, ist schlecht aproach, sollte es Methodenparameter, die Sie, wenn == null (Ansatz von AdapterView) aufbläst.

BTW: Zeile 9 in Ihrem Code, wenn es aufgerufen würde würde NullPointerException werfen, weil es nur für den Fall aufgerufen wird, dass customLayout == null !!!

Verwandte Themen