在onCreate()方法中,我们一般都会遇到setContentView(),那么它到底做了什么?

一个活动继承有两种方式,分别是直接继承Activity,或者继承AppCompatActivity,setContentView()方法的执行就是由这两个基类完成的。

1.Activity

在Activity的setContentView方法主要做了两件事情,首先是通过getWindow获取到window(这个window实际上是phonewindow),调用window的setContentView()方法,其次调用initWindowDecorActionBar()尽心bar的初始化操作。

(1) getWindow

mWindowActivity的成员变量,可以看到在Activity的attach()方法中,mWindow被赋值为PhoneWindow类型。

那么Activity的attach()方法又是什么时候执行的呢?

在ActivityThread的 performLaunchActivity()方法中,首先通过createBaseContextForActivity(r)获取到基本的context,紧接着通过 activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent)创建当前的activity,最后调用activity的attach方法将 mInstrumentation、activity、context绑定起来。

(2) setContentView

由于getWindow()获取到的实际上是PhoneWindow,因此去看PhoneWindow的setContentView()

如上图所示,PhoneWindow的setContentView()方法只要做了三件事情。调用installDecor()方法创建decor,调用mLayoutInflater.inflate(),最后将mContentParentExplicitlySet设置为true。

(a)installDecor()

installDocor()方法中,调用了generateDecor(-1)方法和 generateLayout(mDecor)方法,generateDecor()方法实际上就是获取applicationContext并通过applicationContext创建DecorView。

generateLayout()方法中调用了requestFeature()方法

而requestFeature()方法中首先判断mContentParentExplicitlySet标志位是否为true,如果是的话则抛出异常。

generateLayout()方法中实际上有很多xml模板,如下图 中使用R.layout.screen_simple

R.layout.screen_simple.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"android:orientation="vertical"><ViewStub android:id="@+id/action_mode_bar_stub"android:inflatedId="@+id/action_mode_bar"android:layout="@layout/action_mode_bar"android:layout_width="match_parent"android:layout_height="wrap_content" /><FrameLayoutandroid:id="@android:id/content"android:layout_width="match_parent"android:layout_height="match_parent"android:foregroundInsidePadding="false"android:foregroundGravity="fill_horizontal|top"android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>

R.layout.screen_simple.xml实际上是一个linearLayout布局,内部有viewStub和FrameLayout,其中FrameLayout的id就是content,最终 generateLayout()方法将id为content的FrameLayout赋值给类型为ViewGroup的contentParent并返回

整个结构如下图所示

(b) mLayoutInflater.inflate()

inflate()方法多次重载,如果是merge布局,则调用rInflate()方法,否则调用createViewFromTag()方法创建rootView

在rInflate()方法中也会调用createViewFromTag()方法

createViewFromTag()方法会判断当前的name中是否还有"."如(constraintLayout就是这种类型,或者自定义的view)调用 onCreateView()方法,否则调用createView()方法。

LayoutInflater 是个抽象类,并没有onCreateView()方法的具体 实现,真正实现该方法的是PhoneLayoutInflater,onCreateView()方法内部其实也调用了createView()。其中for循环中的sClassPrefixList如下图。

createView()方法在LayoutInflater中实现,经过重载后,createView()方法内部通过反射得到当前view的全类名,并通过反射得到的构造器创建实例

注:好多细节小点:

a.如果使用merge布局,则merge布局需要作为根布局,且参数为true,rInflate()方法中有说明

(c) 将mContentParentExplicitlySet设置为true

(3) initWindowDecorActionBar()

2.AppCompatActivity

setContentView()是 AppCompatActivity中的方法

发现是getDelegate().setContentView()

实际上getDelegate()得到的是AppCompatDelegateImpl,因此去看的setCntentView()方法

发现首先调用了ensureSubDecor()方法,然后通过mSubDecor找到id为content的控件,清除其中所有的views - removeAllViews()并将当前view添加到容器中。

ensureSubDecor()方法中通过createSubDecor()创建了mSubDecor

createSubDecor()方法很长,首先ensureWindow(),其次调用了mWindow.getDecorView()

ensureWindow()中调用attachToWindow()方法,而mWindow就是在attachToWindow()中被赋值的。传入的参数mHost实际上是AppCompatActivity,被强转成Activity,并获取activity的window,实际上就是PhoneWindow。

AppCompatDelegateImpl的构造器中由于此时传入的window为null,因此不会调用attachToWindow()方法

当ensureWindow()方法调用结束后,调用mWindow.getDecorView()。即创建DecorView的过程,同Activity创建DecorView的过程一样。在createSubDecor()中,执行完这两个方法后,开始进行其它操作。

上图这段红框代码的含义是假设使用abc_screen_simple.xml,通过decorView获取到id为action_bar_activity_content的ContentFrameLayout,并使用PhoneWindow寻找id为content的控件并将其赋值给类型为ViewGroup的windowContentView,将windowContentView控件的id设置为NO_ID,然后将decorView获取到id为action_bar_activity_content的ContentFrameLayout的id设置为content。

R.layout.abc_screen_simple.xml
<androidx.appcompat.widget.FitWindowsLinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/action_bar_root"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:fitsSystemWindows="true"><androidx.appcompat.widget.ViewStubCompatandroid:id="@+id/action_mode_bar_stub"android:inflatedId="@+id/action_mode_bar"android:layout="@layout/abc_action_mode_bar"android:layout_width="match_parent"android:layout_height="wrap_content" /><include layout="@layout/abc_screen_content_include" /></androidx.appcompat.widget.FitWindowsLinearLayout>
abc_screen_content_include.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android"><androidx.appcompat.widget.ContentFrameLayoutandroid:id="@id/action_bar_activity_content"android:layout_width="match_parent"android:layout_height="match_parent"android:foregroundGravity="fill_horizontal|top"android:foreground="?android:attr/windowContentOverlay" /></merge>

友情链接:

参考

参考2

setContentView()做了什么事情?相关推荐

  1. java什么时会出现gc_面试题:java GC发生在会么时候,对什么东西,做了什么事情...

    转自cy609329119的 面试题:"你能不能谈谈,java GC是在什么时候,对什么东西,做了什么事情?" 面试题目: 地球人都知道,Java有个东西叫垃圾收集器,它让创建的对 ...

  2. 无人车巨头每天都在做相同的事情:不惜血本做高精地图是为何?

    来源:腾讯科技 摘要:很多人都关注无人车的发展,殊不知无人车技术中,有十分重要的一环,是无人车的高精地图. 高精地图成为无人车竞赛中的关键一环 目前,很多家无人驾驶公司都在做着同样的事情:绘制同一个路 ...

  3. 【转】做正确的事情,等着被开除(Do the right thing, Wait to get fired)

    原作者博客:https://brendansterne.com/2013/07/11/do-the-right-thing-wait-to-get-fired/ 下面是中文翻译: 我偶然在< T ...

  4. 从任务到可视化,如何理解LSTM网络中的神经元 By 机器之心2017年7月03日 14:29 对人类而言,转写是一件相对容易并且可解释的任务,所以它比较适合用来解释神经网络做了哪些事情,以及神经网

    从任务到可视化,如何理解LSTM网络中的神经元 By 机器之心2017年7月03日 14:29 对人类而言,转写是一件相对容易并且可解释的任务,所以它比较适合用来解释神经网络做了哪些事情,以及神经网络 ...

  5. 要选择做有价值的事情

    创业应该是做对大家对行业有价值的事情,而不是做重复的事情,应该就是类似于做技术 做些有新意的,不能重复造轮子. 选择需要花时间思索.思考,是一件有挑战,并且能够提升自己的事情. 我们应该不断的提高对自 ...

  6. 双十一大促技术只做两件事情?来看看阿里巴巴的技术之道

    作为国内互联网技术的典型代表,阿里巴巴的技术一直备受关注 编者按:本文来自微信公众号"InfoQ"(ID:infoqchina),36氪经授权发布. 支付宝的高可用与容灾架构演进 ...

  7. 坚持做一件事情真的很不容易,首先必须要克服惰性!

    坚持做一件事情真的很不容易,首先必须要克服惰性! 上面是我这个刚出社会的职场小白,最有体会的一句话! 想要真的提高自己的专业水平,除了工作之外,还要不断总结,不断学新的知识. 上面是技术大牛的知识结构 ...

  8. c语言程序执行完main函数后,一个c程序在执行main函数之前和main之后都做了那些事情啊该如何解决...

    当前位置:我的异常网» C语言 » 一个c程序在执行main函数之前和main之后都做了那些 一个c程序在执行main函数之前和main之后都做了那些事情啊该如何解决 www.myexceptions ...

  9. jvm gc垃圾回收机制和参数说明amp;amp;Java JVM 垃圾回收(GC 在什么时候,对什么东西,做了什么事情)

    jvm gc(垃圾回收机制) Java JVM  垃圾回收(GC 在什么时候,对什么东西,做了什么事情) 前言:(先大概了解一下整个过程) 作者:知乎用户 链接:https://www.zhihu.c ...

最新文章

  1. 19.04.27--作业 打字游戏
  2. msdn 上的关于delegate和event的一个例子,理解后加点评论
  3. 3.db2性能和优化
  4. 消息队列—主要消息中间件优势对比
  5. mysql 怎么实现随机查询并分页,不重复查询
  6. 基于CefSharp构建基于Chromium的应用程序
  7. visudo精确用户赋权(sudo)
  8. Quartz 之入门示例
  9. JavaScript事件冒泡和事件委托
  10. python dbf转excel_如何在python中将dbf转换为csv?
  11. 如何将数据库删除干净
  12. DFRobot for Arduino 中级套件
  13. CentOS7.9 查询内网ip
  14. Linux挖矿病毒查杀
  15. BC35 RAI功能应用
  16. 只转不评:112家IT公司薪水一览表
  17. html如何与css样式表链接起来
  18. Vue手脚架的配置以及使用
  19. 信创实际落地如何?详解《2021中国信创产业应用落地研究报告及供应商60强》
  20. SQL 先进先出的库龄计算

热门文章

  1. 苹果天气不显示_今天才知道,简单几步,就能让你的iPhone手机显示锁屏天气
  2. CSS 实现渐变梯形
  3. 红米Redmi Note 11 4G参数配置
  4. JS字符串 替换所有匹配的字符串
  5. linux定时播放音乐,Linux:在录制/播放声音期间的定时
  6. 绘制单个条形图与多个条形图
  7. C#入门级——泛型、泛型类、泛型接口、泛型方法和泛型委托
  8. C语言中bool类型变量的输出格式
  9. 推荐一款本地伪原创工具
  10. facebook 添加好友_Facebook为您的新闻源和VR添加了250个人的群聊,3D照片