- 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.4 rInflateChildren 和 rInflate 方法解析
rInflate 方法主要是遍历传入的 Parent 的子节点,实例化 Parent 的所有子 View。当遍历的时候发现当前 View 还有子 View 则递归调用此方法继续实例化当前 View 的子 View。
这里面主要的操作有:
- parseRequestFocus(),处理请求焦点。
- parseInclude(),处理 include 标签。
- 实例化 1995 或一般 View 并添加到当前 View 的父 View 上。
源码分析:
/** * 循环方法用来深入 xml 的层级并且实例化内部的 View(非根节点 View),这个方法通过调用 rInflate,并使用 Parent 的 Context 作为 * 实例化 View 的 Context。 */ final void rInflateChildren(XmlPullParser parser, View parent, AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException { rInflate(parser, parent, parent.getContext(), attrs, finishInflate); } /** * 循环方法用来深入 xml 的层级并且实例化 view 以及 View 的子 View, * 最后调用 onFinishInflate() 方法 */ void rInflate(XmlPullParser parser, View parent,Context context, final AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException { // 获取当前 xml 解析的深度 final int depth = parser.getDepth(); int type; // 循环遍历 xml 节点 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)) { // 解析<tag>元素,并且设置键控标签在它包含的 View 上。最终调用的是 View 的 view.setTag(key, value);方法 parseViewTag(parser, parent, attrs); } else if (TAG_INCLUDE.equals(name)) { //处理 include 标签 if (parser.getDepth() == 0) { // 最外层使用 include 标签抛出异常。 throw new InflateException("<include /> cannot be the root element"); } // 解析 include 标签引入的布局 parseInclude(parser, context, parent, attrs); } else if (TAG_MERGE.equals(name)) { // 如果是 merge 标签则抛出异常(因为此方法实例化的是 xml 根节点的子 View,所以非根节点不能使用 merge 标签。) throw new InflateException("<merge /> must be the root element"); } else { // 一般性的 View final View view = createViewFromTag(parent, name, context, attrs); final ViewGroup viewGroup = (ViewGroup) parent; // 获取父 View 的 LayoutParams,并在把 View 添加到父 View 的时候带过去 //(这里解释了,为什么自己手动 new 一个 View,添加到父 View 上的时候需要 new 父 View 的 LayoutParams 参数而不是自己的 LayoutParams 参数。) final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs); // 递归遍历实例化 rInflateChildren(parser, view, attrs, true); viewGroup.addView(view, params); } } // 如果父 View 下的所有 View 都完成填充,则调用父 View 的 onFinishInflate() 方法。 if (finishInflate) parent.onFinishInflate(); }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论