android中LayoutInflater.from(context).inflate的分析

HighFUN發表於2013-08-25

在應用中自定義一個view,需要獲取這個view的佈局,需要用到

(LinearLayout) LayoutInflater.from(context).inflate(R.layout.contentitem, null);

這個方法。

一般的資料中的第二個引數會是一個null。通常情況下沒有問題,但是如果我想給這個view設定一個對應的類,然後通過這個類來操作的話就會出問題。

先看下面的例子

 1 <?xml version="1.0" encoding="utf-8"?>
 2 
 3 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 4               android:orientation="vertical"
 5               android:layout_width="match_parent"
 6               android:layout_height="match_parent"
 7               android:background="@color/white">
 8 
 9     <TextView
10             android:layout_width="match_parent"
11             android:layout_height="wrap_content"
12             android:id="@+id/textViewTitle"
13             android:textColor="@color/black"
14             android:gravity="center" android:textSize="26dp"/>
15 
16     <TextView
17             android:layout_width="match_parent"
18             android:layout_height="wrap_content"
19             android:id="@+id/textViewAuthor"
20             android:layout_gravity="left" android:textColor="@android:color/darker_gray" android:textSize="16dp"/>
21 
22     <ImageView
23             android:layout_width="wrap_content"
24             android:layout_height="wrap_content"
25             android:id="@+id/imageView"
26             android:layout_gravity="center_horizontal"
27             android:scaleType="center"/>
28 
29     <TextView
30             android:layout_width="match_parent"
31             android:layout_height="wrap_content"
32             android:id="@+id/textViewContent"
33             android:layout_gravity="center_horizontal" android:textColor="@color/black" android:textSize="20dp"/>
34 
35     <LinearLayout
36             android:layout_width="fill_parent"
37             android:layout_height="2dp"
38             android:layout_gravity="center"
39             android:background="@color/black">
40     </LinearLayout>
41 
42     <TextView
43             android:layout_width="match_parent"
44             android:layout_height="wrap_content"
45             android:id="@+id/textViewOtherInfo"
46             android:layout_gravity="left" android:clickable="true" android:textColor="@android:color/darker_gray"
47             android:textSize="16dp"/>
48 </LinearLayout>

對應的類是

 1 public class ContentItemView extends LinearLayout {
 2 
 3     private TextView title;
 4     private TextView author;
 5     private TextView content;
 6     private TextView otherInfo;
 7     private ImageView contentImage;
 8 
 9     private ContentInfo info;
10 
11     public ContentItemView(Context context) {
12         super(context);
13         init(context);
14     }
15 
16     private void init(Context context) {
17         LinearLayout convertView =
18         (LinearLayout) LayoutInflater.from(context).inflate(R.layout.contentitem, null);
19         title = (TextView) convertView.findViewById(R.id.textViewTitle);
20         author = (TextView) convertView.findViewById(R.id.textViewAuthor);
21         content = (TextView) convertView.findViewById(R.id.textViewContent);
22         otherInfo = (TextView) convertView.findViewById(R.id.textViewOtherInfo);
23         contentImage = (ImageView) convertView.findViewById(R.id.imageView);
24     }
25 }

 

這個自定義view我想將它新增到一個listview中。

 1     public void add(final ContentInfo info) {
 2         ContentItemView contentItemView  = new ContentItemView(context);
 3         contentItemView.setContentInfo(info);
 4         contentItemView.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT));
 5 
 6         data.add(contentItemView);
 7     }
 8 
 9     @Override
10     public View getView(int position, View convertView, ViewGroup parent) {
11         return data.get(position);
12     }

程式執行起來以後,沒有任何問題,但是介面沒有顯示出來,僅僅是在listview中多了一系列黑色的條條

 

如果將

(LinearLayout) LayoutInflater.from(context).inflate(R.layout.contentitem, null);

修改為

(LinearLayout) LayoutInflater.from(context).inflate(R.layout.contentitem, this);

顯示就會正常

 

上面的東西很多資料裡面都有,但是原因是什麼?我在網路上找了很久都沒有找到,於是就自己研究了下程式碼

 1     public View inflate(int resource, ViewGroup root) {
 2         return inflate(resource, root, root != null);
 3     }
 4 
 5     public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
 6         if (DEBUG) System.out.println("INFLATING from resource: " + resource);
 7         XmlResourceParser parser = getContext().getResources().getLayout(resource);
 8         try {
 9             return inflate(parser, root, attachToRoot);
10         } finally {
11             parser.close();
12         }
13     }
14     public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {
15 ........
16                 if (TAG_MERGE.equals(name)) {
17                     if (root == null || !attachToRoot) {
18                         throw new InflateException("<merge /> can be used only with a valid "
19                                 + "ViewGroup root and attachToRoot=true");
20                     }
21 
22                     rInflate(parser, root, attrs, false);
23                 } else {
24                     // Temp is the root view that was found in the xml
25                     View temp;
26                     if (TAG_1995.equals(name)) {
27                         temp = new BlinkLayout(mContext, attrs);
28                     } else {
29                         temp = createViewFromTag(root, name, attrs);
30                     }
31 
32                     ViewGroup.LayoutParams params = null;
33 
34                     if (root != null) {
35                         if (DEBUG) {
36                             System.out.println("Creating params from root: " +
37                                     root);
38                         }
39                         // Create layout params that match root, if supplied
40                         params = root.generateLayoutParams(attrs);
41                         if (!attachToRoot) {
42                             // Set the layout params for temp if we are not
43                             // attaching. (If we are, we use addView, below)
44                             temp.setLayoutParams(params);
45                         }
46                     }
47 
48                   ..............
49                     if (root != null && attachToRoot) {
50                         root.addView(temp, params);
51                     }
52 
53                     // Decide whether to return the root that was passed in or the
54                     // top view found in xml.
55                     if (root == null || !attachToRoot) {
56                         result = temp;
57                     }
58                 }
59 .....
60 }

可以看到在inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)函式中,只有root不等於空的情況下才能夠真正的把view新增到listview中。

看看引數root的含義:@param root Optional view to be the parent of the generated hierarchy 

就是說這個表示的事view的容器是什麼。如果不告訴SDK你要把這個view放到哪裡,當然就不能生成view了。

 

 

相關文章