The correct way to open LayoutInflater. inflater of in Android
- 2021-10-25 07:45:15
- OfStack
Preface
LayoutInflater is used frequently in development, but 1 didn't know much about it
LayoutInflater.from(context).inflate()
The real usage of, let's look at the flow of source code today.
First, let's look at the source code of from ():
/**
* Obtains the LayoutInflater from the given context.
*/
public static LayoutInflater from(Context context) {
LayoutInflater LayoutInflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (LayoutInflater == null) {
throw new AssertionError("LayoutInflater not found.");
}
return LayoutInflater;
}
In fact, it is to obtain the system service corresponding to Context.LAYOUT_INFLATER_SERVICE from Context. The source code for Context implementation and service creation is involved here, so we will not go into it further.
The focus is on the commonly used
inflate()
Methods, these two are commonly used:
inflate(@LayoutRes int resource, @Nullable ViewGroup root)
inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)
Two other methods
inflate(XmlPullParser parser, @Nullable ViewGroup root)
And
inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)
,
The method with two parameters actually calls the method with three parameters
inflate()
Method, only when the three parameters are passed in
root!=null
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}
Then we can directly look at the three parameters
inflate()
Method, where
res.getLayout(resource)
This code has loaded the xml attribute of the root layout of the layout layout that we passed in into XmlResourceParser
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
final Resources res = getContext().getResources();
// Omit code
final XmlResourceParser parser = res.getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
In fact, it will be found here that the last return calls is actually
inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)
This method, the so-called four
inflate()
Method, the other three are just overloads of this method, and the main code is still implemented in this method
This part of the code is long and explains the code in the form of comments
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
synchronized (mConstructorArgs) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");
final Context inflaterContext = mContext;
//1. Pass XmlResourceParser Object is converted to AttributeSet
final AttributeSet attrs = Xml.asAttributeSet(parser);
Context lastContext = (Context) mConstructorArgs[0];
mConstructorArgs[0] = inflaterContext;
View result = root;
try {
//2. In xml Find the root node in, if the type is XmlPullParser.START_TAG Or XmlPullParser.END_DOCUMENT Will exit the loop
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG &&
type != XmlPullParser.END_DOCUMENT) {
// Empty
}
//3. If the root node type is not XmlPullParser.START_TAG An exception will be thrown
if (type != XmlPullParser.START_TAG) {
throw new InflateException(parser.getPositionDescription()
+ ": No start tag found!");
}
final String name = parser.getName();
//4. Determine whether the root node is merge Label
if (TAG_MERGE.equals(name)) {
if (root == null || !attachToRoot) {
throw new InflateException("<merge /> can be used only with a valid "
+ "ViewGroup root and attachToRoot=true");
}
rInflate(parser, root, inflaterContext, attrs, false);
} else {
//5. Create a temporary from the root node view Object
final View temp = createViewFromTag(root, name, inflaterContext, attrs);
ViewGroup.LayoutParams params = null;
if (root != null) {
//6. If root Is not empty, call generateLayoutParams(attrs) Get root Corresponding to LayoutParams Object
params = root.generateLayoutParams(attrs);
// Whether or not attachToRoot
if (!attachToRoot) {
//7. If attachToRoot For false Use the root Default LayoutParams As a temporary view Attributes of the object
temp.setLayoutParams(params);
}
}
//8.inflate xml All child nodes of the
rInflateChildren(parser, temp, attrs, true);
//9. Determine whether you need to create a temporary view attach To root Medium
if (root != null && attachToRoot) {
root.addView(temp, params);
}
//10. Determines that the return value of the method is root Or temporary view
if (root == null || !attachToRoot) {
result = temp;
}
}
} catch (XmlPullParserException e) {
final InflateException ie = new InflateException(e.getMessage(), e);
ie.setStackTrace(EMPTY_STACK_TRACE);
throw ie;
} catch (Exception e) {
final InflateException ie = new InflateException(parser.getPositionDescription()
+ ": " + e.getMessage(), e);
ie.setStackTrace(EMPTY_STACK_TRACE);
throw ie;
} finally {
mConstructorArgs[0] = lastContext;
mConstructorArgs[1] = null;
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
return result;
}
}
XmlResourceParser in layout, which was obtained earlier, contains the attribute data of the heel layout in layout.
6 and 7 are part of the reasons why the width and height attributes of xml layout settings are not effective after using inflate method, and sometimes they are added in RecyclerView. If
root!=null
When attachToRoot is false, the created view will have its own root node attribute value, and the LayoutParam corresponding to root
The decision of 9 determines whether the created view is added to the root, and the decision of 10 determines whether the method returns root or view
Summarize
Different return values can be obtained according to different parameters of inflate
root | attachToRoot | 返回值 |
---|---|---|
null | false(或者true) | 返回resource对应的view对象,但是xml中根节点的属性没有生效 |
!=null | false | 返回resource对应的view对象,并且xml中根节点的属性生效,view对象的LayoutParam与root的LayoutParam对应 |
!=null | true | 返回root对象,对应resource创建的view对象,xml中根节点的属性生效,并且将会添加到root中 |
Note: attachToRoot defaults to
root!=null
Value of
Summarize