Android Window理解(2)---應用窗口創建過程

應用窗口創建

一、創建Window對象

每個應用類窗口window都對應於一個Activity對象。創建應用類窗口都需要先去創建一個Activity。

AmS決定啓動Activity時會先通知客戶端進程,每個客戶端進程都對應於一個ActivityThread對象,啓動Activity任務最後由ActivityThread完成。


以上是Window創建過程,簡單總結如下。

1.ActivityThread收到AMS啓動Activity請求,首先調用到ActivityThread.newActivity()方法,在該方法中根據類名反射生成目標Activity對象。

2.接着調用Activity.attach()方法。

(1) 在該方法中主要是做變量賦值以及最重要的調用PolicyManager.makeNewWindow()生成一個Window對象,而此處其實就是PhoneWindow對象,同時會在其PhoneWindow內部生成WindowManager.LayoutParams對象,而該對象內部type變量標示該Window類型,默認就是Application類型即應用程序窗口。

(2) 爲生成的window對象設置事件回調即Activity對象,這樣Window可以和Activity通信。

(3) 爲生成的window對象設置WindowManager對象,其實就是創建一個WindowManagerImpl對象,該對象負責管理Window中的View。WindowManagerImpl內部是一個WindowManagerGlobal類型的單例引用,所有操作實現最後交給該引用完成。賦值WindowManager到Activity內部。

注意:參數mToken傳遞。該參數原型時AmS中的HistoryRecord對象,由AMS傳遞創建Activity使用。它既是Activity的唯一標示,也是創建Window後的唯一標示。

二、爲Window添加View

爲window添加內容是開發者在Activity生命週期函數onCreate()中使用setContentView()設置的。

簡單總結如下:

1.Activity生命週期函數onCreate()中使用setContentView(),在該函數中實際調用到attach()中生成的PhoneWindow.setContentView(),接着會調用initActionBar()初始化ActionBar。

2.在PhoneWindow.setContentView()函數中

(1)先判斷mContentParent是否爲null,mContentParent是真正放置Window內容的FrameLayout,其id固定爲@android:id/content,開發者指定的layout.xml就是添加到這個Layout中顯示的。如果爲null代表還沒初始化這個PhoneWindow執行installDecor(),不爲null直接remove已加載的View。

(2)執行installDecor(),首先判斷如果mDecor爲null就去新建對象DecorView。DecorView其實就是繼承自FrameLayout的大小爲整個屏幕的ViewGroup,他是PhoneWindow的頂級ViewGroup,所有的View最終根元素就是它。接着又判斷mContentParent是否爲null,如果是則調用generateLayout()加載Window裝飾器layout,而Window裝飾器Layout=mContentParent+Window頂部裝飾(ActionBar/TitleBar)。

(3)generateLayout()通過讀取配置設置Window的FLAG特徵,以及根據開發者配置加載裝飾器Layout。獲取到指定的裝飾器Layout的id之後inflate得到View,使用DecorView將其添加。接着可以獲取mContentParent,不論是何種裝飾器Layout都有存在固定id爲@android:id/content的FrameLayout,用來加載開發者指定的Layout。

這裏的開發者配置有兩個途徑:

  • 在Activity的onCreate()方法中獲取Window對象調用requestFeature()設置,在generateLayout()中使用getLocalFeature()獲取。

  • 在AndroidManifest.xml中爲Activity使用android:theme=”“,在generateLayout()中使用getWindowStyle()獲取。

(4)通過上步可以獲取到用戶需要的ActionBar或者TitleBar,開始設置其對應屬性。至此installDecor()函數執行完成。

(5)通過以上初始化mContentParent、mDecorView完畢,接着就加載開發者指定的layout到mContentParent中,同時回調Activity中的函數實現。

3.最後調用Activity.initActionBar()初始化ActionBar。

以上就是應用類窗口添加View的過程。

三、添加顯示Window

在經過了創建Window對象,爲Window添加View之後就是告訴WmS添加顯示Window。

當Activity準備顯示Window時會通知AmS,經過一系列調用到Activity.makeVisible()。

在makeVisible()方法中:

1.首先獲取Activity內部的WindowManager對象wm。

2.接着調用wm的addView(),其真正實現在WIndowManagerImpl中,在該類中又真正調用到的是WindowManagerGlobal.addView()。而WindowManagerGlobal是個單例模式類,內部維護三個數組用於保存該應用程序中所擁有的窗口狀態,分別是:

  • View[] mViews。即Window的定級View

  • ViewRoot[] mRoots。即ViewRootImpl對象,mViews中每個View都對應一個ViewRootImpl對象。該對象負責Window的View所有操作。

  • WindowManager.LayoutParams[] mParams。每個Window對應一個佈局參數。

3.在WindowManagerGlobal.addView()主要是三個步驟

(1)查找是否已經添加過該窗口,不允許重複添加

(2)判斷是否是一個子Window如果是查找其父Window的View賦值給panelParentView。

(3)創建ViewRootImpl對象,調用其setView()方法完成真正添加

4.在ViewRootImpl.setView()中通過常量mWindowSession類型爲IWindowSession,通知WmS添加該這個窗口,傳入的是ViewRootImpl內部類W繼承自android.view.IWindow.Stub。

PhoneWindow充當一個臨時變量角色管理DecorView,其實真正通知WmS添加的是W。

發佈了40 篇原創文章 · 獲贊 30 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章