6

本來我得到這個錯誤:在衝突的Android錯誤消息:指定的孩子已經有一個家長。你必須調用removeView()對兒童的父母第一

customSection.addView(customLayout); 

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

所以我添加

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

現在得到

java.lang.NullPointerException 

因此,如果孩子有父母,並且我必須先從父母中刪除孩子,爲什麼getParent()返回null?

我有一個抽象片段,它允許派生類爲列表適配器提供自定義佈局。相關代碼:

綁定:

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

我也試過inflater.inflate(R.layout.list_item_custom_section, null) ......假,空/假的,怎麼辦?

編輯:

@allprog,我知道一些清理是必要的。我在一天結束的時候寫了這篇文章,有點匆忙。自從清理了代碼之後,我分離出了​​視圖的綁定和擴展。清理代碼:

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

} 

子類:

@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了它第一,我原來的[蓬頭垢面]代碼,這是解決方案。

+1

什麼是'customSection'?你能在第一次初始化的地方顯示代碼嗎? –

+0

它在getChildItemView(CommonRow row)方法中。 parentView =(LinearLayout)LayoutInflater.from(getActivity())。inflate(R.layout.list_item_custom_section,new LinearLayout(getActivity()),true); – Jack

+0

你可以發佈list_item_custom_section的XML嗎?我懷疑你正在嘗試添加視圖到自己。另外,變量'customSection'仍然需要在某處聲明(並設置)。你可以發佈該代碼嗎? –

回答

12

試試這個:

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

} 

我看了相關的源代碼,getParent應該返回非空值時view有父。你應該確保它實際上有一個父母鑄造和呼籲removeView

希望這可以幫助。

源代碼:

View

public final ViewParent getParent() { 
     return mParent; 
    } 

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

我明白這個部分,問題是customSection.addView(customLayout)失敗,並在OP標題中出現錯誤。因此,我可以整天檢查null,但它仍然不能幫助我將customLayout從其原始的[apparantly null]父級刪除。對我來說沒有意義。 – Jack

+0

添加了源代碼到我的答案。你的意思是你得到這個異常,但'getParent' reuturns null?真奇怪! – suitianshi

+0

並且您是否嘗試將'ViewParent'強制轉換爲'ViewGroup'而不是'LinearLayout'? – suitianshi

2

,我可以看到你的parentView是一個字段變量,這是關鍵。所以我懷疑是怎麼回事:

bind()第一次調用:在創建parentView,它是沒有父然而,工作得很好,但你添加的支票後,父母在這裏失敗。

bind()第二個電話:parentView現在有一個家長,你的額外檢查應現在的工作,但你沒有在前面的步驟。沒有檢查,你在這裏失敗,除了標題。

解決方案:檢查父級的存在並僅在需要時刪除它。

0

首先LayoutInflater膨脹方法總是返回沒有父項的視圖。

如果attachToRoot == trueparentView將是new LinearLayout(getActivity())

如果attachToRoot == falseparentView會膨脹R.layout.list_item_custom_section不管它是。

in both cases ((LinearLayout) customLayout.getParent())將爲空。這就是爲什麼你得到NullPointerException。你可以在LayoutInflater documentation的回報聲明中看到它。

正如上面聲明parentView作爲現場寫得不好的aproach,它應該是你會膨脹,如果== NULL(從適配器視圖的方法)方法的參數。

順便說一句:你的代碼中的第9行如果被調用,它會拋出NullPointerException,因爲它只在以下情況下調用customLayout == null !!!

相關問題