LayoutInflater 是怎么把xml添加到decorview?
来源:互联网 发布:kad网络连接不上 编辑:程序博客网 时间:2024/06/06 04:45
问题
主要问题:
LayoutInflater 是怎么把xml添加到decorview?
衍生问题:
include 为什么不能作为xml资源布局的根节点?
merge 为什么作为xml资源布局的根节点?
先来看setContentView里的 mLayoutInflater.inflate(layoutResID, mContentParent)方法
@Override public void setContentView(int layoutResID) { if (mContentParent == null) { installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, getContext()); transitionTo(newScene); } else { mLayoutInflater.inflate(layoutResID, mContentParent); } final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } }
点inflate进去是以下代码,是把我们自定义的xml和ContentParent传进去
public View inflate(int resource, ViewGroup root) { return inflate(resource, root, root != null); }
继续往里进入inflate方法,resource是我们自定义的xml,root是我们的ContentParent,第三个参数从命名上看意思是,是否添加倒root布局里,如果root传的是null则为false,反之则为true。往下看重要的方法是–>利用res.getLayout(resource)方法得到xml解析器,把xml文件解析出来,之后是inflate(parser, root, attachToRoot),
public View inflate(int resource, 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(); } }
我们进入inflate(parser, root, attachToRoot)这个方法继续探索,方法如下
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) { synchronized (mConstructorArgs) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate"); *//先拿xml的各种属性 * final AttributeSet attrs = Xml.asAttributeSet(parser); Context lastContext = (Context)mConstructorArgs[0]; mConstructorArgs[0] = mContext; **//把root赋值给result** View result = root; try { // Look for the root node. 先去找根节点 int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // Empty } 。。。省略若干行 //首先判断根节点是不是merge标签 if (TAG_MERGE.equals(name)) { if (root == null || !attachToRoot) { //如果是merge标签,但是 root == null || !attachToRoot就抛出一个异常,因为如果使用merge标签,肯定有得有一个顶层的ViewGroup标签来放这个加载的layout throw new InflateException("<merge /> can be used only with a valid " + "ViewGroup root and attachToRoot=true"); } 如果root不为空就用以下方法把逐层解析添加到root(ViewGroup)里面,这里传的false rInflate(parser, root, attrs, false, false); } else { //当是一些常用的标签的时候,首先会利用createViewFromTag方法来生成我们自定义的根节点,比如LinearLayout标签 // Temp is the root view that was found in the xml final View temp = createViewFromTag(root, name, attrs, false); ViewGroup.LayoutParams params = null; if (root != null) { if (DEBUG) { System.out.println("Creating params from root: " + root); } // Create layout params that match root, if supplied //利用父节点的root.generateLayoutParams方法生成子节点的属性(这里的父节点就是id为content的Framelayout) params = 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()方法,把父节点解析出来的属性设置到子节点上; temp.setLayoutParams(params); } } if (DEBUG) { System.out.println("-----> start inflating children"); } // Inflate all children under temp //加载所有子节点 这里传的true rInflate(parser, temp, attrs, true, 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.addView(temp, params); } // Decide whether to return the root that was passed in or the // top view found in xml. if (root == null || !attachToRoot) { result = temp; } } } catch (XmlPullParserException e) { InflateException ex = new InflateException(e.getMessage()); ex.initCause(e); throw ex; } catch (IOException 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; } }
再看rInflat方法
void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs, boolean finishInflate, boolean inheritContext) throws XmlPullParserException, IOException { final int depth = parser.getDepth(); int type; //while循环,通过遍历循环来解析child节点,当不是最后一个标签的时候会走以下方法逐层解析,并添加到parent,如果只加载一个View,拿肯定不会走这个方法了 while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { if (type != XmlPullParser.START_TAG) { continue; } final String name = parser.getName(); if (TAG_REQUEST_FOCUS.equals(name)) { parseRequestFocus(parser, parent); } else if (TAG_TAG.equals(name)) { parseViewTag(parser, parent, attrs); } else if (TAG_INCLUDE.equals(name)) { //这里是判断include标签,当该布局里面没有东西的时候,会抛出一个异常 inclide标签不能作为根节点 if (parser.getDepth() == 0) { throw new InflateException("<include /> cannot be the root element"); } parseInclude(parser, parent, attrs, inheritContext); } else if (TAG_MERGE.equals(name)) { //merge只能作为根节点,如果出现在子节点中会抛出异常。 throw new InflateException("<merge /> must be the root element"); } else { //一层一层遍历解析 final View view = createViewFromTag(parent, name, attrs, inheritContext); final ViewGroup viewGroup = (ViewGroup) parent; final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs); rInflate(parser, view, attrs, true, true); viewGroup.addView(view, params); } } //当为merge标签时候 不走这个方法,为普通标签时会走这个方法 //控制回调函数,具体以后在讲 if (finishInflate) parent.onFinishInflate(); }
小结:每一个Activity都有一个关联的Window对象,用来描述应用程序窗口。
每一个窗口内部又包含了一个DecorView对象,Decorview对象用来描述窗口的视图–xml布局,以上大概记录了xml布局的加载过程,
上述是创建DecorView的过程
附上图片更易理解
阅读全文
0 0
- LayoutInflater 是怎么把xml添加到decorview?
- LayoutInflater 到底怎么把xml添加到decorview
- DecorView如何添加到Window
- 怎么把UltraEdit添加到右键菜单
- DecorView如何添加到Window上
- 怎么把maven工程的包添加到tomcat上
- xcode怎么把自定义代码添加到代码库CodeSnippets
- 怎么把XML文件导入到csdn博客啊?
- 顶层视图DecorView添加到窗口的过程
- 该怎么把这个“JiaThis分享到按钮”添加到5D6D论坛呢?
- 怎么把同一数据源里的数据添加到不同的listView里面
- 怎么把注册信息一下子添加到3个数据库的表中
- 求教xml文件怎么sqlldr导入到oracle中,xml里面是表数据
- XML文件怎么添加注释
- 把程序添加到开始菜单
- 用editplus编辑PHP,每次新键时,要到“others...”中才有PHP,怎么把PHP添加到新建中
- 怎么把QLabel添加进QGraphicsItem
- 怎么把xml文件转为java文件
- 在Ubuntu和Windows下用命令行升级NodeJS和npm的版本
- idea安装配置tomcat
- HDU 4312 切比雪夫转化 曼哈顿距离
- 二进制转十进制
- C语言printf和scanf--c语言学习笔记7
- LayoutInflater 是怎么把xml添加到decorview?
- 简单的汇率转换工具---初试AJAX
- 一、vault
- ANR源码分析之InputDispatcher Timeout
- react native listview组件 探索记录
- MYSQL外键(Foreign Key)的使用
- 撤销(undo)和重做(redo)的C++完美实现
- ajax 跨域 headers JavaScript ajax 跨域请求 +设置headers 实践
- 给定三边判断是否是直角三角形