LayoutInflater源码分析
为什么要看这个类的源码呢 ?是因为在使用RecyclerView时,对Item进行getLayoutParams操作时,报了空指针异常。通过对源码的分析,才知道问题是出在了是否正确的使用了LayoutInflater。这是一个比较冷门的问题,也是一个比较容易被忽略的问题。但是我们每次将布局转化成View时,都会使用到这个类,所以想要好好分析一下,顺便记录下来,加深自己的理解和记忆,同时也希望可以帮助到其他的人。
首先我们来看一下出问题的代码:
看源码,首先从最常用的方法开始看,其实也可以说,就看常用的方法就够了。所以我们要从inflate()的源码开始看起。
// TODO 补充:源代码的位置
在LayoutInflater.java中,一共有4个重载的inflate(),我们一个一个慢慢的看。
// 第一个
/*** Inflate a new view hierarchy from the specified xml resource. Throws* {@link InflateException} if there is an error.** @param resource ID for an XML layout resource to load (e.g.,* <code>R.layout.main_page</code>)* @param root Optional view to be the parent of the generated hierarchy.* @return The root View of the inflated hierarchy. If root was supplied,* this is the root View; otherwise it is the root of the inflated* XML file.*/public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {return inflate(resource, root, root != null);}// 第二个/*** Inflate a new view hierarchy from the specified xml node. Throws* {@link InflateException} if there is an error. ** <p>* <em><strong>Important</strong></em> For performance* reasons, view inflation relies heavily on pre-processing of XML files* that is done at build time. Therefore, it is not currently possible to* use LayoutInflater with an XmlPullParser over a plain XML file at runtime.** @param parser XML dom node containing the description of the view* hierarchy.* @param root Optional view to be the parent of the generated hierarchy.* @return The root View of the inflated hierarchy. If root was supplied,* this is the root View; otherwise it is the root of the inflated* XML file.*/public View inflate(XmlPullParser parser, @Nullable ViewGroup root) {return inflate(parser, root, root != null);}
可以看到,第一个inflate(resource,root)是两个参数的inflate,它实际上是调用了三个参数的inflate(int resource, ViewGroup root, boolean attachToRoot)。第二个inflate(parser,root)的第一个参数是XmlPullParser,它调用的是三个参数的inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)。开始分析第三个inflate
//第三个/*** Inflate a new view hierarchy from the specified xml resource. Throws* {@link InflateException} if there is an error.** @param resource ID for an XML layout resource to load (e.g.,* <code>R.layout.main_page</code>)* @param root Optional view to be the parent of the generated hierarchy (if* <em>attachToRoot</em> is true), or else simply an object that* provides a set of LayoutParams values for root of the returned* hierarchy (if <em>attachToRoot</em> is false.)* @param attachToRoot Whether the inflated hierarchy should be attached to* the root parameter? If false, root is only used to create the* correct subclass of LayoutParams for the root view in the XML.* @return The root View of the inflated hierarchy. If root was supplied and* attachToRoot is true, this is root; otherwise it is the root of* the inflated XML file.*/
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) + ")");}// 把resource转化为parser final XmlResourceParser parser = res.getLayout(resource);try {return inflate(parser, root, attachToRoot);} finally {parser.close();}}
查看源码发现,这个方法调用了三个参数的inflate(XmlPullParser parser, ViewGroup root, boolean 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");}// 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) {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 {// Don't retain static reference on context.mConstructorArgs[0] = lastContext;mConstructorArgs[1] = null;Trace.traceEnd(Trace.TRACE_TAG_VIEW);}return result;}}
在从上往下查看源码的过程中,我们看到了这样一句话:
params = root.generateLayoutParams(attrs);咦,我们的问题就是出在params上,params报空,因此我们往上看,看到了这一句: if (root != null) 原来问题出在了root上,查看我们出问题的代码,(写出出问题的代码)
再往下看:
if (!attachToRoot) {// Set the layout params for temp if we are not// attaching. (If we are, we use addView, below)temp.setLayoutParams(params);}
也就是说,只有attachToRoot = false 时,才会将params设置到temp上去。
LayoutInflater源码分析相关推荐
- 【Android 插件化】VirtualApp 源码分析 ( 启动应用源码分析 | HomePresenterImpl 启动应用方法 | VirtualCore 启动插件应用最终方法 )
文章目录 一.启动应用源码分析 1.HomeActivity 启动应用点击方法 2.HomePresenterImpl 启动应用方法 3.VirtualCore 启动插件应用最终方法 一.启动应用源码 ...
- 【Android 启动过程】Activity 启动源码分析 ( Activity -> AMS、主线程阶段 )
文章目录 一.Activity 启动源码分析 ( Activity -> AMS 阶段 ) 一.Activity 启动源码分析 ( Activity -> AMS 阶段 ) 调用 star ...
- DialogFragment源码分析
2019独角兽企业重金招聘Python工程师标准>>> 目录介绍 1.最简单的使用方法 1.1 官方建议 1.2 最简单的使用方法 1.3 DialogFragment做屏幕适配 2 ...
- android字符显示流程图,Android应用层View绘制流程与源码分析
1 背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原 ...
- Dialog源码分析
目录介绍 1.简单用法 2.AlertDialog源码分析 2.1 AlertDialog.Builder的构造方法 2.2 通过AlertDialog.Builder对象设置属性 2.3 build ...
- 源码分析 merge 标签减少布局层级的秘密(Android Q)
源码分析 merge 标签减少布局层级的秘密(Android Q) 我在<Android 渲染性能优化--你需要知道的一切!>一文中介绍过,merge 标签用于减少 View 树的层次来优 ...
- Android应用Activity、Dialog、PopWindow、Toast窗口添加机制及源码分析
1 背景 之所以写这一篇博客的原因是因为之前有写过一篇<Android应用setContentView与LayoutInflater加载解析机制源码分析>, 然后有人在文章下面评论和微博 ...
- leakcanary1.5源码分析
文章目录 介绍 使用 问题 源码分析 总结 介绍 内存泄漏检测工具,square公司出品,github地址https://github.com/square/leakcanary. gradle引用: ...
- Android 12 新APP启动画面(SplashScreen API)简介源码分析
以往的启动画面 默认情况下刚启动APP时会显示一会白色背景 如果把这个启动背景设置为null,则一闪而过的白色会变成黑色 如果把启动Activity设置为背景透明[< item name=&qu ...
最新文章
- java poi 导出 国际化_更好用的excel国际化多语言导出
- python语音翻译-python利用有道翻译实现“语言翻译器”的功能
- SAP Spartacus 服务器端渲染找不到 index 视图的问题
- angluar cdk_零分钟即可在容器开发套件(CDK)上实现云运营
- webpaper网页出题语言
- xlsx文件和csv文件的相互转化
- 吴恩达发布了大型X光数据集,斯坦福AI诊断部分超越人类 | AAAI 2019
- stl之set集合容器应用基础
- Photoshop 入门教程「6」如何更改图像大小?
- layui分页完整实例php,使用 layui 后端分页的实例
- 典型相关分析(cca)原理_全网最细的图文详解——手把手教你不会代码一样做RDA/CCA分析!...
- c语言easyx背景图片,C++之设置背景图片(Easyx)
- 【产品速递】云和恩墨ZDBM数据库备份一体机
- redis分布式代理工具选型与功能验证
- python qq群自动加入_Python实现向QQ群成员自动发邮件的方法
- es6 去掉空格_ES6之字符串
- 【Android驱动】aw9106驱动代码流程
- 天下国家之事,败于小人者十一,败于君子者十九(转)
- JAVA键盘录入 分支结构if swtich语句+循环结构for while语句 练习
- Android中复制到剪切板