Android 加载setContentView加载的流程

137 阅读1分钟

setContentView(xml) 加载布局可以看出,activity, window, view 之间的关系

继承Activity时使用:
requestWindowFeature(Window.FEATURE_NO_TITLE)
继承AppCompatActivity时使用,对继承Activity的无效:
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)

注意:设置WindowFeature 时需要在setContentView之前,因为在添加布局文件到DecorView上时需要使用这个样式

继承 AppCompatActivity

1. AppCompatDelegate.create
    初始化 2步骤
2. AppCompatDelegateImpl
3. ensureSubDecor();
4. ViewGroup contentParent = mSubDecor.findViewById(android.R.id.content);
// 渲染布局 到 contentParent
5. LayoutInflater.from(mContext).inflate(resId, contentParent); 

步骤3. ensureSubDecor 创建

createSubDecor
 --> ensureWindow //在AppCompatActivity的onCreate时,创建window 并且检查window
 --> mWindow.getDecorView() //获取Window(PhoneWindow) 中的DecorView
     --> installDecor //PhoneWindow中的getDecorView 方法调用的,做了如下两件事:
         --> 1.generateDecor //new DecorView(x, x, x, x()) 直接 new DecorView 返回
         --> 2. generateLayout // 获取 mContentParent,设置状态栏、窗口样式、导航栏颜色、获取布局
             --> mDecor.onResourcesLoaded(mLayoutInflater, layoutResource) // 设置界面布局,
             将 mLayoutInflater布局加入到 layoutResource 中 的控件Id 为R.id.content
     // 也是为什么出现 subDecor        
     //获取 继承 Activity         
     --> ViewGroup windowContentView = (ViewGroup)mWindow.findViewById(android.R.id.content);
       --> windowContentView.setId(View.NO_ID); //将原始Id 置为空
           // 将R.id.action_bar_activity_content ID 修改为 R.id.content
           contentView.setId(android.R.id.content); 
       --> mWindow.setContentView(subDecor); // 设置 subDecor

这就完成了 setContentView 加入布局的流程

步骤5: 创建View 的流程

//先创建RootView(也就是布局的根View)
View temp = createViewFromTag(root, name, inflaterContext, attrs);
    --> if (-1 == name.indexOf('.')) {
            //系统的View
            view = onCreateView(context, parent, name, attrs);
              --> PhoneLayoutInflater.createView(name, attrs)
                      //prefix 前缀
                      "android.widget.",
                      "android.webkit.",
                      "android.app.",
                      "android.view.",
                  --> View view = createView(name, prefix, attrs)
        } else {
            //自定义的View
            view = createView(context, name, null, attrs);
        }
        //以上两种创建View, 都会回到 这里使用反射获取全路径控价
        1. clazz = Class.forName(prefix != null ? (prefix + name) : name, false,
        mContext.getClassLoader()).asSubclass(View.class);
        //获取控件后,就拿构造对象
        2. constructor = clazz.getConstructor(mConstructorSignature);
        //创建控件
        3. View view = constructor.newInstance(args);

继承 Activity

getWindow().setContentView //调用的是 PhonwWindow 的setContentView
  --> installDecor // 直接就和 AppCompatActivity 的 步骤3. ensureSubDecor 创建一样

  --> mLayoutInflater.inflate(layoutResID, mContentParent);// 渲染布局 到 mContentParent