继之后接着说
之前我们分析了setContentView方法的相关代码 接下来说说LayoutInflater的方法
LayoutInflater源码分析
- 与setContentView相关
在PhoneWindow的generateLayout中调用了
View in = mLayoutInflater.inflate(layoutResource, null);复制代码
- LayoutInflater中获取实例化方法
/** * 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; }复制代码
- inflate方法相关
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) { return inflate(resource, root, root != null); } public View inflate(XmlPullParser parser, @Nullable ViewGroup root) { return inflate(parser, root, root != null); }复制代码
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(); } }复制代码
最后发现都需要调用
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) { synchronized (mConstructorArgs) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate"); final Context inflaterContext = mContext; final AttributeSet attrs = Xml.asAttributeSet(parser); Context lastContext = (Context) mConstructorArgs[0]; mConstructorArgs[0] = inflaterContext; //定义返回值 初始化传入形参 root View result = root; try { // 找到根节点 int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { } //验证type是否为Start_Tag 保证xml文件正确 if (type != XmlPullParser.START_TAG) { throw new InflateException(parser.getPositionDescription() + ": No start tag found!"); } //type为 root node final String name = parser.getName(); if (DEBUG) { System.out.println("**************************"); System.out.println("Creating root view: " + name); System.out.println("**************************"); } if (TAG_MERGE.equals(name)) { //处理 merge相关 //root需要非空 且attachToRoot为空 if (root == null || !attachToRoot) { throw new InflateException("can be used only with a valid " + "ViewGroup root and attachToRoot=true"); } //递归inflate 方法调用 rInflate(parser, root, inflaterContext, attrs, false); } else { //根据tag节点创建view对象 final View temp = createViewFromTag(root, name, inflaterContext, attrs); ViewGroup.LayoutParams params = null; if (root != null) { if (DEBUG) { System.out.println("Creating params from root: " + root); } //根据root生成LayoutParams params = root.generateLayoutParams(attrs); if (!attachToRoot) { //如果attachToRoot为flase 则调用setLayoutParams temp.setLayoutParams(params); } } if (DEBUG) { System.out.println("-----> start inflating children"); } //递归inflate剩下的children rInflateChildren(parser, temp, attrs, true); if (DEBUG) { System.out.println("-----> done inflating children"); } // We are supposed to attach all the views we found (int temp) // to root. Do that now. if (root != null && attachToRoot) { //root非空且attachToRoot=true则将xml文件的root view加到形参提供的root里 root.addView(temp, params); } // Decide whether to return the root that was passed in or the // top view found in xml. if (root == null || !attachToRoot) { //返回xml里解析的root view result = temp; } } } catch (XmlPullParserException e) { InflateException ex = new InflateException(e.getMessage()); ex.initCause(e); throw ex; } catch (Exception e) { InflateException ex = new InflateException( parser.getPositionDescription() + ": " + e.getMessage()); ex.initCause(e); throw ex; } finally { // Don't retain static reference on context. mConstructorArgs[0] = lastContext; mConstructorArgs[1] = null; } Trace.traceEnd(Trace.TRACE_TAG_VIEW); //返回参数root或xml文件里的root view return result; } }复制代码
相关inflate参数的结果
- 相关方法解析 在Inflate中多次被调用的rInflate
void rInflate(XmlPullParser parser, View parent, Context context, AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException { final int depth = parser.getDepth(); int type; //XmlPullParser解析器的标准解析模式 while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { //找到start_tag节点 if (type != XmlPullParser.START_TAG) { continue; } //获取Name标记 final String name = parser.getName(); //private static final String TAG_REQUEST_FOCUS = "requestFocus"; //处理requestFocus if (TAG_REQUEST_FOCUS.equals(name)) { parseRequestFocus(parser, parent); // private static final String TAG_TAG = "tag"; //处理tag } else if (TAG_TAG.equals(name)) { parseViewTag(parser, parent, attrs); //private static final String TAG_INCLUDE = "include"; //处理include } else if (TAG_INCLUDE.equals(name)) { //如果是根节点则抛出异常 if (parser.getDepth() == 0) { throw new InflateException("cannot be the root element"); } parseInclude(parser, context, parent, attrs); //private static final String TAG_MERGE = "merge"; //处理merge merge需要是xml中的根节点 } else if (TAG_MERGE.equals(name)) { throw new InflateException(" must be the root element"); } else { final View view = createViewFromTag(parent, name, context, attrs); final ViewGroup viewGroup = (ViewGroup) parent; final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs); rInflateChildren(parser, view, attrs, true); viewGroup.addView(view, params); } } //parent的所有子节点都处理完毕的时候回onFinishInflate方法 if (finishInflate) { parent.onFinishInflate(); } } //可以添加自定义逻辑 protected void onFinishInflate() { }复制代码