1. 程式人生 > >android Fragment java.lang.IllegalStateException:The specified child already has a parent.

android Fragment java.lang.IllegalStateException:The specified child already has a parent.

在做專案的時候 ,做到了一個Activity裡面有兩個Tab切換,每一個Tab是一個Fragment展示內容,當兩個Tab來回切換的時候,報了一個錯誤

經過查詢原因,原來是Fragment中OnCreateView()的方法呼叫錯了:


正確的方法應該是:

查閱多方資料得知,我們都LayoutInflater的使用存在誤區

我們最常用的便是 LayoutInflater的inflate方法,這個方法過載了四種呼叫方式,分別為:

1. public View inflate(int resource, ViewGroup root)

2.  public View inflate(int resource, ViewGroup root, boolean attachToRoot)

3.public View inflate(XmlPullParser parser, ViewGroup root)

4.public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)

這四種使用方式中,我們最常用的是第一種方式, inflate方法的主要作用就是將xml轉換成一個View物件,用於動態的建立佈局。雖然過載了四個方法,但是這四種方法最終呼叫的,還是第四種方式。第四種方式也很好理解,內部實現原理就是利用Pull解析器,對Xml檔案進行解析,然後返回View物件。

inflate方法有三個引數,分別是

1. resource 佈局的資源id

2. root 填充的根檢視

3.attachToRoot是否將載入的檢視繫結到根檢視中

一般情況下,我們將BaseAdapter中的getView()方法:中根檢視設定為null,

public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = inflate(R.layout.item_row, null);
    }
    return convertView;
}
和我們將根檢視設定為false
@Override
public View getView(int position, View convertView, ViewGroup parent) {

if (convertView == null) {
convertView = inflater.inflate(R.layout.item_list, parent,false);
}
return convertView;
}
的區別是,如果在listview中的Item中根佈局設定高度為40dp的話,第一種就沒有效果。

經過看原始碼分析,當我們傳進來的root引數不是空的時候,並且attachToRoot是false的時候,會重新給設定引數。

若我們採用 convertView = inflater.inflate(R.layout.item_list, null);方式填充檢視,item佈局中的根檢視的layout_XX屬性會被忽略掉,然後設定成預設的包裹內容方式

除了使用這種方式,我們還可以設定item佈局的根檢視為包裹內容,然後設定內部控制元件的高度等屬性,這樣就不會修改顯示方式了