Android 窗口是如何创建的?

2,240 阅读3分钟

前言

在WmS看来窗口并不是Window类,而是一个View类。WmS收到用户消息后,需要把消息发送到窗口,View类其实并不能直接接受传递过来的消息,而接受消息的必须是IWindow类,实现IWindow类的是ViewRoot.W类,每一个W内部都包含了一个View变量。

WmS并不在意该窗口是哪个应用程序的,关心的是活跃窗口,WmS按一定得规则判断哪个窗口处于活动状态,然后把用户消息给W类,W类再把用户消息传递给内部View变量,然后再由View对象完成剩下的消息处理。

窗户有几种类型?

Framework定义了三种窗口类型,三种窗口类型的定义在WindowManager类里面。

  • 应用窗口。应用窗口一般指该窗口对应一个Activity,由于加载Activity是由Ams完成的,所以对于应用程序创建应用类窗口只能在Activity内部完成。
  • 子窗口。子窗口是指该窗口必须要有一个父窗口,父窗口可以是一个应用类窗口也可以是任何其他的窗口。
  • 系统窗口。系统窗口不需要对应任何Activity,也不需要有父窗口。应用程序是没有办法创建系统窗口的,只有系统进程可以创建系统窗口。

那么该怎么创建应用窗口呢?

1.每个应用类窗口都对应一个Activity对象,所以创建应用类窗口需要创建Activity对象。当AmS要启动某个Activity时就会通知客户端进程,每个客户端进程都对应一个ActivityThread类,所以需要ActivityThread启动Activity。

启动某个Activity实际是构造一个Activity对象,使用ClassLoader从程序文件中装载指定的Activity对应的Class文件。

2.创建完成Activity对象后调用Activity的attach()方法,attach()的作用就是为刚刚创造好的Activity设置内部变量。

3.为该Activity创建Window对象。

4.给Window对象中的mWindowManager变量赋值。

5.然后就需要给该窗口添加真正的View或者ViewGroup。从performLaunchActivity()调用callActivityOnCreate()开始,然后经一系列调用到Activity的onCreate()方法,在onCreate()方法中调用setContentView()方法实际是调用了其对应的Window对象的setContentView()方法。

6.接着会调用到PhoneWindow的setContentView,首先调用installDecor()为Window类添加窗口装饰,其实就是标题栏,程序中设置的layout.xml界面被包含在窗口装饰中,就是窗口内容。窗口装饰也是ViewGroup,窗口装饰和它内部的内容加起来就是我们所说的窗口,或者叫做Window界面。

7.把创建的窗口通知WmS,让WmS把窗口显示在屏幕上。当Activity准备好后会通知Ams,然后Ams经过一系列调用到Activity的makeVisible(),该方法将真正完成把窗口添加进Wms中。

8.在makeVisible方法中,首先获得该Activity内部的WindowManager对象,然后调用该对象的addView()方法。

9.调用WindowManagerImpl的addView()方法,流程如下:

  • 检查添加的窗口是否已经添加过,不能重复添加。
  • 如果添加的窗口是子窗口类型,找到父窗口并保存在临时变量panelParentView中,该变量作为后面调用ViewRoot的setView()参数。
  • 创建一个新的ViewRoot
  • 调用ViewRoot的setView()。

10.完成新建一个ViewRoot对象后,需要把新建的ViewRoot对象添加到mRoots对象中。

11.调用ViewRoot对象的setView方法。流程如下:

  • 给ViewRoot的重要变量赋值。
  • 调用requestLayout(),发出界面重绘请求。
  • 调用sWindowSession.add(),通知Wms添加窗口。

创建子窗口或系统窗口过程和上面的类似。

如有问题请留言,转载请注明出处。

备注:以上部分思想来自于《Android内核剖析》