setContentView源码分析
当我们在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源码分析的更多相关文章
- Android应用层View绘制流程与源码分析
1 背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原 ...
- android高级---->AsyncTask的源码分析
在Android中实现异步任务机制有两种方式,Handler和AsyncTask,它在子线程更新UI的例子可以参见我的博客(android基础---->子线程更新UI).今天我们通过一个小的案例 ...
- Android Handler处理机制 ( 一 )(图+源码分析)——Handler,Message,Looper,MessageQueue
android的消息处理机制(图+源码分析)——Looper,Handler,Message 作为一个大三的预备程序员,我学习android的一大乐趣是可以通过源码学习 google大牛们的设计思想. ...
- 源码分析——从AIDL的使用开始理解Binder进程间通信的流程
源码分析——从AIDL的使用开始理解Binder进程间通信的流程 Binder通信是Android系统架构的基础.本文尝试从AIDL的使用开始理解系统的Binder通信. 0x00 一个AIDL的例子 ...
- Android事件传递机制详解及最新源码分析——View篇
摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 对于安卓事件传递机制相信绝大部分开发者都听说过或者了解过,也是面试中最常问的问题之一.但是真正能从源码角度理解具体事件传递流程的相信并不多, ...
- Android事件传递机制详解及最新源码分析——ViewGroup篇
版权声明:本文出自汪磊的博客,转载请务必注明出处. 在上一篇<Android事件传递机制详解及最新源码分析--View篇>中,详细讲解了View事件的传递机制,没掌握或者掌握不扎实的小伙伴 ...
- Android事件传递机制详解及最新源码分析——Activity篇
版权声明:本文出自汪磊的博客,转载请务必注明出处. 在前两篇我们共同探讨了事件传递机制<View篇>与<ViewGroup篇>,我们知道View触摸事件是ViewGroup传递 ...
- Android HandlerThread 源码分析
HandlerThread 简介: 我们知道Thread线程是一次性消费品,当Thread线程执行完一个耗时的任务之后,线程就会被自动销毁了.如果此时我又有一 个耗时任务需要执行,我们不得不重新创建线 ...
- onCreate源码分析
原文地址Android面试题-onCreate源码都没看过,怎好意思说自己做android Activity扮演了一个界面展示的角色,堪称四大组件之首,onCreate是Activity的执行入口,都 ...
随机推荐
- Linux-Centos快速安装Docker
卸载之前的docker sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-l ...
- supervisor的安装与使用
Ubuntu安装使用supervisor 进程管理工具 安装 apt-get install supervisor 查看是否安装成功 pgrep supervisord # 返回进程号则成功 改配置文 ...
- 记一次 .NET 某物管后台服务 卡死分析
一:背景 1. 讲故事 这几个月经常被朋友问,为什么不更新这个系列了,哈哈,确实停了好久,主要还是打基础去了,分析 dump 的能力不在于会灵活使用 windbg,而是对底层知识有一个深厚的理解,比如 ...
- 图片管够!用Python做了个图片识别系统(附源码)
本项目将使用python3去识别图片是否为色情图片,会使用到PIL这个图像处理库,并且编写算法来划分图像的皮肤区域 介绍一下PIL: PIL(Python Image Library)是一种免费的图像 ...
- NC17857 起床困难综合症
NC17857 起床困难综合症 题目 题目描述 21 世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm 一直坚持与起床困难综合症作斗争 ...
- Java服务假死后续之内存溢出
一.现象分析 上篇博客说到,Java服务假死的原因是使用了Guava缓存,30分钟的有效期导致Full GC无法回收内存.经过优化后,已经不再使用Guava缓存,实时查询数据.从短期效果来看,确实解决 ...
- can板间通信代码学习
一.板间通信 板间通信是底盘与上下云台之间的通信 A型板和两个C型板 主要可以分成两个方面,一是哨兵的模式选择和遥控器数据的解码:二是对于CAN发送和接收数据的处理. 二.CAN的板间通信相关函数 c ...
- 部署CDH集群环境准备
一.系统centOS7以上,至少三台主机 添加ip 主机名映射关系:(每台主机都要做) vim /etc/hosts 127.0.0.1 localhost localhost.localdomain ...
- 常用的函数式接口_Consumer接口和常用的函数式接口_Consumer接口的默认方法andThen
Consumer接口 java,util.function.Consumer接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定 抽象方法:accept C ...
- 深入Synchronized各种使用方法
深入学习Synchronized各种使用方法 在Java当中synchronized通常是用来标记一个方法或者代码块.在Java当中被synchronized标记的代码或者方法在同一个时刻只能够有一个 ...