1. 秦子帅的博客首页
  2. Android

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

布局结构分析

在分析AppCompatActivity.setContentView原理之前,我们先看一下它的布局结构,
我们做一个这样的布局,布局中只有TextView,并且设置AppCompatActivity主题为noTitle的:

然后我通过Layout Inspector查看布局结构:

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局
自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

源码分析

点击进入查询源码:

我们发现是代理模式,继续查询getDelegate(),点进去查看:

我们又发现了AppCompatDelegate,先看一下此类的继承关系:
怎么查看继承关系?

  • Windows:ctrl + h
  • Mac:control + h

下面看一下继承关系图:

 

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

然后看一下AppCompatDelegate create方法:

我们终于发现在create方法中是根据版本的不同来创建AppCompatDelegate实现类的。为什么这样做呢?当然是为了兼容问题!
现在我们具体看一下setContentView中到底写了什么?通过寻找,发现AppCompatDelegateImplV9中进行了重写:

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局
具体分析

我们会发现三个方法中都执行了 ensureSubDecor();
我们来分析一下此段代码:

解读ensureSubDecor();,我们打开:

我们注意到了 mSubDecor = createSubDecor();,那mSubDecor是什么?我们索引一下,其实它是ViewGroup

继续看createSubDecor()方法:

createSubDecor方法我们要好好分析一下,首先要知道我们当前研究的AppCompatActivity 是no title的。然后初始化了DecorView

mWindow.getDecorView()我们放在后面讲,继续看代码,然后走到这个地方,发现有个mWindowNoTitle判断

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

mWindowNoTitle到底是什么?我们继续查一下

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

原来是判断activity是否有title,这就明白了,我们显然是没有,直接走else,继续往下看代码:

 

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

从图上看mOverlayActionMode,经过在本类AppCompatDelegateImplV9查找,发现在requestWindowFeature(FEATURE_ACTION_MODE_OVERLAY)才会执行进来,所以直接走else

subDecor 前面已经提到了是ViewGroup,加载了abc_screen_simple布局,我们来看一下abc_screen_simple布局是什么样子:

发现布局中有include布局,打开发现就是一个ContentFrameLayout,注意它的ID:

看完这些我们继续回归createSubDecor(),继续往下看,首先加载ActionBarContextView

然后会发现ContentFrameLayout以及windowContentView (ViewGroup)的实例化,windowContentView 加载了android.R.id.content的布局:

继续往下看,我们将将 ContentFrameLayout 的 id 更改成了 content

下面就剩下我们还没搞清楚的两行代码了:

首先我们从代码中看出是初始化了DecorView内部控件,打开 mWindow.getDecorView(),发现是在Window类下:

我们查询下实现类PhoneWindow

mDecor 就是DecorView,然后我们看一下installDecor();方法,因为代码太多,我就截图重要部分:

我们逐步分析上面的代码,我们最先看到的就是实例化mDecor

然后我们继续往下看,对mContentParent做了判断,mContentParent其实就是ViewGroup

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

我们打开generateLayout(mDecor)看看,因为代码实在太多,我就粘贴比较重要的部分吧:

从上面代码得知加载了R.layout.screen_simple布局,并在onResourcesLoaded方法中添加到了DecorView里,然后找到此布局的R.id.content控件 ,并直接return contentParent
看一下screen_simple布局:

现在mWindow.getDecorView();弄清楚了,接下来就剩下mWindow.setContentView(subDecor);了。我们继续研究:

subDecor熟悉吧?我们在上面createSubDecor()方法中都仔细的分析完了 继续分析 setContentView

PhoneWindow中我们可以看到setContentView具体的实现方法:

我们一起分析上面代码,首先是执行:

mContentParent知道吧?上面已经讲了在installDecor()方法中,就是ViewGroup,具体是什么大家去上面仔细看。 然后继续往下看:

非常重要的一行代码,是把subDecor添加到mContentParent中,subDecor是什么?上边已经仔细讲过了。

至此AppCompatDelegateImplV9setContentView方法中的ensureSubDecor();全部讲完了。我们先回顾一下AppCompatDelegateImplV9setContentView方法:

 

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

我上面分析比较详细了吧?如果你还是比较懵逼,我这写一个方法流程图,
里面写的不是很全,只是一个思路,希望大家能静下心去翻源码:

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

大家可以关注我的微信公众号:「秦子帅」一个有质量、有态度的公众号!

自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

原文始发于:自定义View(4)-源码分析AppCompatActivity的setContentView加载布局

发布者:秦子帅,转转请注明出处:http://qinzishuai.cn/index.php/2018/11/10/a4dff6429a/

联系我们

912241847

在线咨询:点击这里给我发消息

邮件:qzs531156@163.com

QR code