Obtain the LayoutInflater object method and the inflate method parameters.
I. Three methods for obtaining LayoutInflater
1,
LayoutInflater layoutInflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
2,
LayoutInflater layoutInflater = LayoutInflater.from(MainActivity.this);
3,
LayoutInflater layoutInflater = MainActivity.this.getLayoutInflater();
In fact, you can view their source code and find that the last two methods finally call the context. getSystemService (Context. LAYOUT_INFLATER_SERVICE) of the first method ). However, to view the source code of the third method, you need to take a look. Because activity. getLayoutInflater () actually calls getLayoutInflater () of the Window class, which is an abstract class. According to the annotation of this class, you can view its subclass PhoneWindow, which is an internal class and cannot be found using development tools. You need to find it manually. You can find it from the sdk file directory. For example, my name is "D: \ Android \ Sdk \ sources \ android-23 \ com \ android \ internal \ policy ". You can also search for this class directly in the sdk directory.
In fact, the View has a static inflate method. Even the LayoutInflater object has been created internally for you. The method source code is as follows:
public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) { LayoutInflater factory = LayoutInflater.from(context); return factory.inflate(resource, root); }
Ii. Parameters of the inflate Method
I used to be confused with the inflate method. It is confusing when the value of ViewGroup object and attachToRoot is passed in. So I analyzed the source code.
When writing the ListView Adapter, The inflate method is always called in the getView method. For example:
convertView = LayoutInflater.from(mContext).inflate(R.layout.push_to_refresh_header, parent, false);
The source code of this inflate method is:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) { final Resources res = getContext().getResources(); if (DEBUG) { Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" (" + Integer.toHexString(resource) + ")"); } final XmlResourceParser parser = res.getLayout(resource); try { return inflate(parser, root, attachToRoot); } finally { parser.close(); } }
At this time, the incoming ViewGroup object is not nullt, And the boolean attachToRoot is set to false.
When dynamically adding a layout, I learned the following method:
View refreshView = layoutInflater.inflate(R.layout.push_to_refresh_header, null);linearLayout.addView(refreshView);
The source code of this inflate method is:
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) { return inflate(resource, root, root != null); }
In this case, the input ViewGroup object is null.
It can be seen that when the inflate method of two parameters is called, it will take the value of the parameter attachToRoot as the judgment value of the ViewGroup object not equal to null, and pass it to another inflate method with three parameters.
In the end, the following inflate method will be called. Here, we only need to pay attention to ViewGroup root, boolean attachToRoot, and the returned result, so I will omit others.
1 public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) { 2 synchronized (mConstructorArgs) { ......
9 View result = root; 10 11 try { ......
32 33 if (TAG_MERGE.equals(name)) { ......
40 } else { 41 // Temp is the root view that was found in the xml 42 final View temp = createViewFromTag(root, name, inflaterContext, attrs); 43 44 ViewGroup.LayoutParams params = null; 45 46 if (root != null) { ......
51 // Create layout params that match root, if supplied 52 params = root.generateLayoutParams(attrs); 53 if (!attachToRoot) { 54 // Set the layout params for temp if we are not 55 // attaching. (If we are, we use addView, below) 56 temp.setLayoutParams(params); 57 } 58 } ......
70 71 // We are supposed to attach all the views we found (int temp) 72 // to root. Do that now. 73 if (root != null && attachToRoot) { 74 root.addView(temp, params); 75 } 76 77 // Decide whether to return the root that was passed in or the 78 // top view found in xml. 79 if (root == null || !attachToRoot) { 80 result = temp; 81 } 82 } 83 84 }
......
102 return result;103 }104 }
In row 3, the initial value of the returned result is root.
Then, only the if statement with 79th rows of the entire method will modify the result. The condition is that root is null, or attachToRoot is false. The temp can find the initial value in row 42nd. In fact, the above comment tells us that temp is the root view in the layout file we passed in.
In the getView method of the Adapter, although the input root is not null, but the attachToRoot is false, the returned value is the root view in the input layout file, used to initialize and modify controls in the layout. The above Dynamic Layout adding method also applies when the input root is null.
Why does the getView method not directly input null? I failed to find the reason from the source code. I only know that when the input ViewGroup object is null, an error will be reported during running. If the Adapter is null, it means that the Adapter object is not initialized. What if the root is uploaded, but the value of attachToRoot is true? It also reports an error.
Let's take a look at the if statement in line 1. It indicates that the root parameter is not null, and when the attachToRoot parameter is true, the temp and its layout parameters are added to the root.
Therefore, in the above case, the root is actually the ListView. In the parent class AdapterView of ListView, the annotation of the method does not support the addView method. Once called, an error is reported.
The way I add a layout dynamically above can be replaced:
View refreshView = layoutInflater.inflate(R.layout.push_to_refresh_header, linearLayout);
The Root View of the parent layout can be passed in. It will automatically generate the value of attachToRoot to true. Then add the root View in the layout to the root.