### 前言
在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添加窗口。
創建子窗口或系統窗口過程和上面的類似。
如有問題請留言,轉載請注明出處。