当我们在Activity中调用setContentView,它到底做了什么呢

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}

我们跳转到AppCompatActivity的setContentView方法

@Override
public void setContentView(@LayoutRes int layoutResID) {
//返回了AppCompatDelegate对象
getDelegate().setContentView(layoutResID);
}

然后又调用了getDelegate().setContentView()

@NonNull
public AppCompatDelegate getDelegate() {
if (mDelegate == null) {
//跳转到create()方法可以看到,该方法返回的是一个AppCompatDelegateImpl对象
mDelegate = AppCompatDelegate.create(this, this);
}
return mDelegate;
}

我们直接去AppCompatDelegateImpl中查看setContentView方法,可以看到,Activity中的

setContentView最后调用了AppCompatDelegateImpl的setContentView方法

@Override
public void setContentView(View v) {
ensureSubDecor();
ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews();
LayoutInflater.from(mContext).inflate(resId, contentParent);
mOriginalWindowCallback.onContentChanged();
}

ensureSubDecor又调用了createSubDecor方法

private ViewGroup createSubDecor() {
....
//步骤1
//mWindow是PhoneWindow,该对象是在Activity.java attach()方法中初始化
//该方法会触发DecorView的创建
mWindow.getDecorView();
...
//根据不同的情形加载不同的布局文件来初始化subDecor,具体过程可以不细究
...
//步骤2
//可以先看完之后的步骤可以再来看这里
//调用PhoneWindow.setContentView()方法,将创建好的subDecor添加到mContentParent,
//mContentParent是在installDecor方法中调用generateLayout()创建出来的
//在之后的Android版本中,我们的布局其实是添加到了subDecor中,而subDecor又会添加到
//PhoneWindow.mContentParent,mContentParent其实是DecorView的一个子View,初始化过程见installDecor方法
mWindow.setContentView(subDecor);
}

mWindow.getDecorView会调用PhoneWindow的getDercorView(),里面会调用installDecor()

private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
//该方法会直接new DecorView()
mDecor = generateDecor(-1);
...
...
}
if (mContentParent == null) {
//生成一个FrameLayout,用于添加AppCompatDelegateImpl.createSubDecor()
//中创建的subDecor,该view是在setContentView中添加的,见步骤2
mContentParent = generateLayout(mDecor);
final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
R.id.decor_content_parent); if (decorContentParent != null) {
mDecorContentParent = decorContentParent;
...
...
}

generateDecor()方法会创建一个DecorView,继承自FrameLayout,是PhoneWindow的内部类,

新版本的Android源码已独立出来

protected DecorView generateDecor(int featureId) {
...
...
return new DecorView(context, featureId, this, getAttributes());
}

generateLayout方法根据不同的主题样式来加载不同系统的布局,

最终返回一个FrameLayout对象,可以通过findViewById(android.R.id.content)获取

protected ViewGroup generateLayout(DecorView decor){
...
...
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
...
...
return contentParanet;
}

回到步骤2

最后我们回到AppCompatDelegateImpl.setContentView中去

@Override
public void setContentView(int resId) {
ensureSubDecor(); //这个对象就是PhoneWindow下面的generateLayout()创建出来的FrameLayout
ViewGroup contentParent = (ViewGroup) mSubDecor.findViewById(android.R.id.content);
contentParent.removeAllViews(); //最后将我们传进来的布局文件实例化,然后添加进去
LayoutInflater.from(mContext).inflate(resId, contentParent); //最后会回调onContentChanged()生命周期方法
mOriginalWindowCallback.onContentChanged();
}

setContentView流程

总结:

setContentView()会触发DecorView的创建,最后会将我们的布局文件添加到DecorView,完成布局文件的加载,

这也就是为什么我们在onCreate()方法中获取不到view的宽高,因为该过程只加载了布局,并没有对布局View进行大小的测量.

setContentView源码分析的更多相关文章

  1. Android应用层View绘制流程与源码分析

    1  背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原 ...

  2. android高级---->AsyncTask的源码分析

    在Android中实现异步任务机制有两种方式,Handler和AsyncTask,它在子线程更新UI的例子可以参见我的博客(android基础---->子线程更新UI).今天我们通过一个小的案例 ...

  3. Android Handler处理机制 ( 一 )(图+源码分析)——Handler,Message,Looper,MessageQueue

    android的消息处理机制(图+源码分析)——Looper,Handler,Message 作为一个大三的预备程序员,我学习android的一大乐趣是可以通过源码学习 google大牛们的设计思想. ...

  4. 源码分析——从AIDL的使用开始理解Binder进程间通信的流程

    源码分析——从AIDL的使用开始理解Binder进程间通信的流程 Binder通信是Android系统架构的基础.本文尝试从AIDL的使用开始理解系统的Binder通信. 0x00 一个AIDL的例子 ...

  5. Android事件传递机制详解及最新源码分析——View篇

    摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 对于安卓事件传递机制相信绝大部分开发者都听说过或者了解过,也是面试中最常问的问题之一.但是真正能从源码角度理解具体事件传递流程的相信并不多, ...

  6. Android事件传递机制详解及最新源码分析——ViewGroup篇

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 在上一篇<Android事件传递机制详解及最新源码分析--View篇>中,详细讲解了View事件的传递机制,没掌握或者掌握不扎实的小伙伴 ...

  7. Android事件传递机制详解及最新源码分析——Activity篇

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 在前两篇我们共同探讨了事件传递机制<View篇>与<ViewGroup篇>,我们知道View触摸事件是ViewGroup传递 ...

  8. Android HandlerThread 源码分析

    HandlerThread 简介: 我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了.如果此时我又有一 个耗时任务需要执行,我们不得不重新创建线 ...

  9. onCreate源码分析

    原文地址Android面试题-onCreate源码都没看过,怎好意思说自己做android Activity扮演了一个界面展示的角色,堪称四大组件之首,onCreate是Activity的执行入口,都 ...

随机推荐

  1. 开发工具-MySQL下载地址

    更新记录 2022年6月10日 完善标题. 商业版下载 商业版下载地址 https://edelivery.oracle.com/ 使用Oracle账号登录即可下载. 官方下载 https://dev ...

  2. R语言读取matlab中数据

    1. 在matlab中将数据保存到*.mat 文件夹 save("data.mat","data","label")#将data和label ...

  3. kubernetes之常用核心资源对象

    部门产品线本身是做DEVOPS平台,最近部署架构也在往K8S上靠了,不得不学一下K8S.自己搭建了K8S集群与harbor仓库来学习. 1.kubernetes之常用核心资源对象 1.1.K8s服务部 ...

  4. 使用Java编写一个日期时间封装类

    package base; import java.util.GregorianCalendar; import java.util.StringTokenizer; import java.util ...

  5. 【python基础】第04回 变量常量

    本章内容概要 1. python 语法注释 2. python 语法之变量常量 3. python 基本数据类型(整型(int),浮点型(float),字符串(str)) 本章内容详解 1. pyth ...

  6. 论文解读(GCC)《Efficient Graph Convolution for Joint Node RepresentationLearning and Clustering》

    论文信息 论文标题:Efficient Graph Convolution for Joint Node RepresentationLearning and Clustering论文作者:Chaki ...

  7. rhel安装程序

    Linux下软件分类     rpm软件包,包管理器 yum     deb软件包,包管理器 apt     源代码软件包            一般为".tar.gz".&quo ...

  8. 攻防世界MISC进阶区 61-63

    61.肥宅快乐题 得到swf文件,但是用PotPlayer打不开,用浏览器应该可以打开,打开后可以在npc的对话中看到一段base64 解密后就可以得到flag 62.warmup 得到一张png和一 ...

  9. C# 实例解释面向对象编程中的接口隔离原则

    在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...

  10. Centos7借助docker部署mysql,提供远程链接服务

    Centos7 借助docker部署mysql,并提供远程连接服务 安装docker 运行docker 注意安装docker和运行docker的步骤很简单,可以参考我学习docker的笔记 docke ...