Android error message conflict: the specified child already has a parent. You must first call removeView () on the parent parent

I originally got this error:

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

at

customSection.addView(customLayout); 

So I added

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

and now we get

 java.lang.NullPointerException 

So, if the child has a parent and I must first remove the child from the parent, why does getParent () return null?

I have an abstract snippet that allows derived classes to provide a custom layout for a list adapter. Relevant Code:

Binding:

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

I also tried inflater.inflate(R.layout.list_item_custom_section, null) ... false, null / false, what gives?

EDIT:

@allprog, I knew some sort of cleanup was needed. I wrote this at the end of the day somewhat in a hurry. Since then, I have cleaned up the code and separated the binding and inflating of the view. Cleared 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); } } 

Child class:

  @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 got it first, with my source [unmanaged] code, which was the solution.

+6
source share
3 answers

try the following:

 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 read the source code, getParent should return a non-zero value if view has a parent. You have to make sure that it actually has a parent before casting and calling removeView

Wish it helps.

source:

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 parent first."); } 
+12
source

As I can see, your parentView is a field variable, it is a key. So, I suspect this is really happening:

The first call to bind() : you create a parentView and it does not yet have a parent, customSection.addView(customLayout); works fine, but after adding a check for the parent it doesn't work here.

The second call to bind() : parentView now has a parent, and your added check should work now, but you have not completed the previous step. Without verification, you are not here with an exception in the title.

Solution: check for a parent and remove it only if necessary.

+2
source

First of all, the LayoutInflater bloat method always returns a view without a parent.

if attachToRoot == true parentView will be: new LinearLayout(getActivity())

if attachToRoot == false parentView will be pumped by R.layout.list_item_custom_section , whatever that is.

in both cases ((LinearLayout) customLayout.getParent()) will be null. That is why you get a NullPointerException . You can see this in the return statement in the LayoutInflater documentation .

As stated above, declaring parentView , because the field is bad aproach , it must be a parameter of the method that you will inflate if == null (approach from AdapterView).

BTW: line 9 in your code, if it were called, it would throw a NullPointerException , because it is only customLayout == null if customLayout == null !!!

0
source

All Articles