- CompoundButton 源码分析
- LinearLayout 源码分析
- SearchView 源码解析
- LruCache 源码解析
- ViewDragHelper 源码解析
- BottomSheets 源码解析
- Media Player 源码分析
- NavigationView 源码解析
- Service 源码解析
- Binder 源码分析
- Android 应用 Preference 相关及源码浅析 SharePreferences 篇
- ScrollView 源码解析
- Handler 源码解析
- NestedScrollView 源码解析
- SQLiteOpenHelper/SQLiteDatabase/Cursor 源码解析
- Bundle 源码解析
- LocalBroadcastManager 源码解析
- Toast 源码解析
- TextInputLayout
- LayoutInflater 和 LayoutInflaterCompat 源码解析
- TextView 源码解析
- NestedScrolling 事件机制源码解析
- ViewGroup 源码解析
- StaticLayout 源码分析
- AtomicFile 源码解析
- AtomicFile 源码解析
- Spannable 源码分析
- Notification 之 Android 5.0 实现原理
- CoordinatorLayout 源码分析
- Scroller 源码解析
- SwipeRefreshLayout 源码分析
- FloatingActionButton 源码解析
- AsyncTask 源码分析
- TabLayout 源码解析
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
5.1 inflate 方法解析
inflate 方法主要是把布局资源实例化成 View 并返回。
通过 获取 LayoutInflater 的三种方式 我们知道,通过布局文件填充成 View 对象最终调用的是下面两个方法:
public View inflate(int resource, ViewGroup root, boolean attachToRoot) { if (DEBUG) System.out.println("INFLATING from resource: " + resource); //获取布局资源的 xml 解析器,注意:在开头的时候我们强调过,普通的 xml 是不被支持的,必须是经过编译器处理过的。 XmlResourceParser parser = getContext().getResources().getLayout(resource); try { return inflate(parser, root, attachToRoot); } finally { parser.close(); } }
最终调用的是此方法:
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) { synchronized (mConstructorArgs) { Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate"); // from 传入的 Context final Context inflaterContext = mContext; // 判断 parser 是否是 AttributeSet,如果不是则用 XmlPullAttributes 去包装一下。 final AttributeSet attrs = Xml.asAttributeSet(parser); // 保存之前的 Context Context lastContext = (Context) mConstructorArgs[0]; // 赋值为传入的 Context mConstructorArgs[0] = inflaterContext; // 默认返回的是传入的 Parent View result = root; try { // 查找开始标签 int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // Empty } //如果没找到有效的开始标签则抛出 InflateException 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("**************************"); } // 如果根节点是“merge”标签 if (TAG_MERGE.equals(name)) { // 根节点为空或者不添加到根节点上,则抛出异常。 // 因为“merge”标签必须是要被添加到父节点上的,不能独立存在。 if (root == null || !attachToRoot) { throw new InflateException("<merge /> can be used only with a valid " + "ViewGroup root and attachToRoot=true"); } // 递归实例化 root(也就是传入 Parent)下所有的 View rInflate(parser, root, inflaterContext, attrs, false); } else { // temp 是当前 xml 的根节点的 View。通过父 View、View 名、Context、属性,来实例化 View。也即实例化根节点的 View。 final View temp = createViewFromTag(root, name, inflaterContext, attrs); ViewGroup.LayoutParams params = null; // 如果传入 Parent 不为空 if (root != null) { if (DEBUG) { System.out.println("Creating params from root: " + root); } // 创建父 View 类型的 LayoutParams 参数 params = root.generateLayoutParams(attrs); if (!attachToRoot) { // 如果不把填充的 View 关联在父 View 上,则把父 View 的 LayoutParams 参数设置给它 // 如果把填充的 View 关联在父 View 上,则会走下面 addView 的逻辑 temp.setLayoutParams(params); } } if (DEBUG) { System.out.println("-----> start inflating children"); } // 实例化根节点 View 下面的所有子 View。 // TODO .................. rInflate(parser, temp, attrs, true); if (DEBUG) { System.out.println("-----> done inflating children"); } // Google 建议关联所有找到的 View // 如果根节点不为 null,并且需要把根节点 View 关联到 Parent 上,则使用 addView 方法把布局填充成的 View 树添加到 Parent 上。 if (root != null && attachToRoot) { root.addView(temp, params); } // 决定返回的 RootView(也即传入的 Parent)还是 xml 中的根节点的 View。 // 如果传入的 Parent 为空 或 实例化的 View 不添加到 Parent 上,则返回布局文件的根节点的 View // 否则,返回 Parent 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. // 把这之前保存的 Context 从新放回全局变量中。 mConstructorArgs[0] = lastContext; mConstructorArgs[1] = null; } Trace.traceEnd(Trace.TRACE_TAG_VIEW); return result; } }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论