Android setContentView,Window,PhoneWindow and DecorView
从 Activity 的 setContentView(R.layout.activity_main)
开始。
1 | public void setContentView(int layoutResID) { |
这里调用了 getWindow().setContentView
方法,那这个 getWindow() 是什么呢?
1 | /** |
从上面的 getWindow() 方法可以看到,获取的是当前 activity 的 Window 对象,如果 activity 不可见,返回 null。而 Window 是一个抽象类,所以这里的 mWindow.setContentView 方法调用的是 Window 实现类的方法。那 Window 的实现类是什么呢?
在 Activity 类的 attach 方法中,可以看出,PhoneWindow 即是 Window 的实现类。
1 | final void attach(Context context, ActivityThread aThread, |
所以我们直接去看 PhoneWindow 的 setContentView 方法。
1 | public void setContentView(int layoutResID) { |
如果 mContentParent == null,也就是当前内容未加载到窗口中,第一次加载时,调用 installDecor() 方法。
1 | private void installDecor() { |
installDecor() 方法中先是通过 generateDecor() 方法创建 DecorView 对象,DecorView 继承于 FrameLayout,用来作为整个PhoneWindow的根视图,但此时还只是个空架子。
1 | protected DecorView generateDecor(int featureId) { |
创建完成后,根据用户的设置,通过 generateLayout() 方法根据 Theme 从系统中选择创建默认布局。
引用 事件分发机制原理 中的例子阐述 Window、PhoneWindow 及 DecorView 之间的关系:
简单来说,Window是一个抽象类,是所有视图的最顶层容器,视图的外观和行为都归他管,不论是背景显示,标题栏还是事件处理都是他管理的范畴,它其实就像是View界的太上皇(虽然能管的事情看似很多,但是没实权,因为抽象类不能直接使用)。
而 PhoneWindow 作为 Window 的唯一亲儿子(唯一实现类),自然就是 View 界的皇帝了,PhoneWindow 的权利可是非常大大,不过对于我们来说用处并不大,因为皇帝平时都是躲在深宫里面的,虽然偶尔用特殊方法能见上一面,但想要完全指挥 PhoneWindow 为你工作是很困难的。
而上面说的 DecorView 是 PhoneWindow 的一个内部类,其职位相当于小太监,就是跟在 PhoneWindow 身边专业为 PhoneWindow 服务的,除了自己要干活之外,也负责消息的传递,PhoneWindow 的指示通过 DecorView 传递给下面的 View,而下面 View 的信息也通过 DecorView 回传给 PhoneWindow。