从源码角度深入理解LayoutInflater

关于LayoutInflater,在开发中经常会遇到,特别是在使用ListView的时候,这个几乎是必不可少。今天我们就一起来探讨LayoutInflater的工作原理。

一般情况下,有两种方式获得一个LayoutInflater实例:

LayoutInflater inflater1, inflater2;inflater1 = LayoutInflater.from(this);inflater2 = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

但是当我们查看源码的时候,却发现这两种其实是一种,只不过第一种将第二种封装了一下,我们看看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;}

获得LayoutInflater对象之后,我们就可以调用inflate来获得View对象了,inflate方法的源码如下:

public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {return inflate(resource, root, root != null);}

这里调用了一个inflate的一个重载方法,这个重载方法的最后一个参数和root有关,如果我们的root为空,那么最后一个参数默认为false。我们看看这个重载方法:

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();}}

可以看出,先是拿到布局的xml资源,然后,获得一个XmlResourceParser 对象,最后inflate(parser, root, attachToRoot);又是调用一个重载方法:

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;View result = root;try {// Look for the root node.int type;while ((type = parser.next()) != XmlPullParser.START_TAG &&type != XmlPullParser.END_DOCUMENT) {// Empty}if (type != XmlPullParser.START_TAG) {throw new InflateException(parser.getPositionDescription()+ “: No start tag found!”);}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)) {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 {// Temp is the root view that was found in the xmlfinal View temp = createViewFromTag(root, name, inflaterContext, attrs);ViewGroup.LayoutParams params = null;if (root != null) {if (DEBUG) {System.out.println(“Creating params from root: ” +root);}// Create layout params that match root, if suppliedparams = root.generateLayoutParams(attrs);if (!attachToRoot) {// Set the layout params for temp if we are not// attaching. (If we are, we use addView, below)temp.setLayoutParams(params);}}if (DEBUG) {System.out.println(“—–> start inflating children”);}// Inflate all children under temp against its context.rInflateChildren(parser, temp, attrs, true);if (DEBUG) {System.out.println(“—–> done inflating children”);}(root != null && attachToRoot) {root.addView(temp, params);}(root == null || !attachToRoot) {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);return result;}}切忌贪婪,恨不得一次玩遍所有传说中的好景点,

从源码角度深入理解LayoutInflater

相关文章:

你感兴趣的文章:

标签云: