Android View加载显示过程分析

从 setContentView 开始

public void setContentView(@LayoutRes int layoutResID) {  
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

PhotoWindow调用 LayoutInflater.from(context).inflate(layoutResID, mContentParent) 初始化, 意味着所有从xml加载View都会使用LayoutInflater

获取LayoutInflater对象
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)

// 实际操作类是 PhoneLayoutInflater
registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,  
             new CachedServiceFetcher<LayoutInflater>() {
         @Override
          public LayoutInflater createService(ContextImpl ctx) {
             return new PhoneLayoutInflater(ctx.getOuterContext());
         }});
inflate()
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {  
    synchronized (mConstructorArgs) {

        final Context inflaterContext = mContext;
        final AttributeSet attrs = Xml.asAttributeSet(parser);
        Context lastContext = (Context) mConstructorArgs[0];
        mConstructorArgs[0] = inflaterContext;
        View result = root;

        try {
            ……

            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 xml
                final View temp = createViewFromTag(root, name, inflaterContext, attrs);

                ViewGroup.LayoutParams params = null;

                if (root != null) {
                    ……
                    // Create layout params that match root, if supplied
                    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(params);
                    }
                }
                ……

                // Inflate all children under temp against its context.
                rInflateChildren(parser, temp, attrs, true);

                // 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;
                }
            }

        } …… 
          省略异常处理部分
          ……

        return result;
    }
}
  • root不为空才会读取Layout Params属性
  • attachToRoot 为 True ,返回的是 root 对象。否则返回的是 xml 创建的根标签指定的 View

View 显示在界面上过程

  • ActivityThread::handleResumeActivity 将DecorView 添加到Window, 最后会调用ViewRootImpl::setView
  • 解密刷新主要是ViewRootImpl.requestLayout(), 里面调用scheduleTraversals(), 绘制关键方法performTraversals, 里面调用 performMeasure, performLayout, performDraw

参考文档