返回介绍

5.4 rInflateChildren 和 rInflate 方法解析

发布于 2024-12-23 22:04:08 字数 2612 浏览 0 评论 0 收藏 0

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文