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


Related articles: