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的执行入口,都 ...
随机推荐
- 拥抱 OpenAPI 3:springdoc-openapi 食用指南
概述 使用 springdoc-openapi 可以快速为 springboot 项目生成规范的 API 文档,具体使用步骤如下: 依赖配置 在 pom.xml 加入内容,即可开始使用: <de ...
- node zlib压缩模块了解一下
压缩: 从index.html压缩成index.html.gz const zlib = require('zlib'); const gzip = zlib.createGzip();const f ...
- Kali MSF漏洞利用
一.前言 漏洞利用是获得系统控制权限的重要途经.用户从目标系统中找到容易攻击的漏洞,然后利用该漏洞获取权限,从而实现对目标系统的控制. 二.Metasploitable Metasploitable是 ...
- UiPath图片操作截图的介绍和使用
一.截图(Take Screenshot)的介绍 截取指定的UI元素屏幕截图的一种活动,输出量仅支持图像变量(image) 二.Take Screenshot在UiPath中的使用 1. 打开设计器, ...
- Linux文本管理命令
touch命令: 创建空文件:touch newfile 也可以使用重定向符(>)创建空文件: > newfile 刷新文件时间: touch 已经存在的文件 cp命令:文件的复制 选项: ...
- 更好的Android多线程下载框架
/** * 作者:Pich * 原文链接:http://me.woblog.cn/ * QQ群:129961195 * Github:https://github.com/lifengsofts */ ...
- P3480 [POI2009]KAM-Pebbles 题解
题目链接 首先,这道题看上去就是个博弈论,很显然的 \(Nim\) 游戏. 因为每一个的取法都和它的上一位有关. 有一种非常显然的转换方式 :我们把这若干堆石子从前向后做一个差分 . 我们记 \(a_ ...
- 动画 ---Animejs 简单使用与源码解析
Anime是什么 Anime有什么用 Anime是作何做的 requireAnimationFrame() engine(){ // 处理让多个帧运动起来 play() step()} ani ...
- java-Stream的总结
JAVA中的Stream 01.什么是Stream Stream是JDK8中引入,Stream是一个来自数据源的元素序列并支持聚合操作.可以让你以一种声明的方式处理数据,Stream 使用一种类似用 ...
- Iterator接口介绍和迭代器的代码实现
定义:Iterator接口是Java集合框架中的一员. 作用:Collection接口与Map接口主要用于存储元素. 常用方法: boolen hasNext(); //判断游标右边是否还有元 ...