Tip
這篇文章是由設(shè)計模式中的 Buidler 模式中引出的榛了,由于 AlertDialog 使用了 builder 模式霜大,在分析 Dialog 的過程中革答,用到的 WindowManager 來完成到屏幕的展示,如果想了解 Builder 模式的可以看 這里
正文
在 Dialog 的 show 方法的最后途茫,是通過調(diào)用 WindowManager 的 addView 方法將視圖最后顯示到了屏幕上溪食,接下來就深入了解 addView 方法的工作過程
其實,不單是 Dialog 栅组,Activity 玉掸、Toast 等需要顯示到屏幕上的內(nèi)容醒叁,都是通過 WindowManager 完成的泊业。
WindowManager 在系統(tǒng)注冊時會保存 WindowManagerImpl 對象到 ContextImpl 類中的一個靜態(tài) Map 中的脱吱,使用 Context 的 getSystemService 方法提供單例的對象认罩。
工作過程
第一步 WindowManger 的方法
Dialog 中的 mWindowManager 為 WindowManagerImpl 對象箱蝠,是全局單例的對象宦搬,在 Dialog 的構(gòu)造函數(shù)中初始化 mWindowManager 參數(shù)的值间校,并在 Dialog 的構(gòu)造函數(shù)中創(chuàng)建 Window 對象页慷,Window 對象創(chuàng)建之后,調(diào)用其 setWindowManager 方法建立與 WindowManagerImpl 之間的聯(lián)系
setWindowManager 中主要完成了根據(jù) Window 對象創(chuàng)建新的與 Window 有聯(lián)系的 WindowManagerImpl 實例的任務(wù)酒繁,并為 Window 中的屬性 mWindowManager 賦值,在 Java 層上 Window 與 WindowManager 建立了第一步聯(lián)系揭绑。
mWindowManger = new WindowManagerImpl(mDisplay,window);
由于 Java 中對象傳遞為值傳遞郎哭,所以 Dialog 中將 WindowManagerImpl 傳遞到 Window 對象中進(jìn)行操作,WindowManagerImpl 對象發(fā)生改變邦蜜,Dialog 中的 WindowManagerImpl 對象也會跟著改變的亥至,所以,在 Dialog 的 show 方法中井辆,最終調(diào)用的也是與當(dāng)前 Window 有關(guān)聯(lián)的 WindowManagerImpl 對象的 addView 方法
注意:這里是使用單例的 WindowManagerImpl 溶握,通過不同的 Window 蒸播,構(gòu)建了與 Window 有關(guān)聯(lián)的 WindowManagerImpl 對象
第二步 WindowManagerGlobal 的方法
在 WindowManagerImpl 中存在一個單例存在的 WindowManagerGlobal 對象萍肆,在 WindowManagerImpl 的各個方法中塘揣,將任務(wù)的執(zhí)行過程傳遞到了 WindowManagerGlobal 中宿崭,在傳遞過程中除了將 View、LayoutParams 傳遞奖蔓,還將 WindowManagerImpl 中關(guān)聯(lián)的 window 對象也一起傳遞
在 WindowManagerGlobal 的 addView 方法中讹堤,最后通過 ViewRootImpl 的 setView 將 View 顯示,具體過程是與 WindowManagerService 的交互
ViewRootImpl
繼承自 Handler 類疑务,是作為 native 層和 Java 層 View 系統(tǒng)通信的橋梁
ViewRootImpl 中保存了當(dāng)前線程梗醇,開發(fā)過程中在子線程中更新 UI 會拋出異常,是因為 ViewRootImpl 是 UI 線程中創(chuàng)建的廊镜,并不是因為只有 UI 線程才可以更新 UI
第三步 建立與 WindowManagerService 的聯(lián)系
在 ViewRootImpl 的構(gòu)造方法中唉俗,會調(diào)用 WindowManagerGlobal 的 getWindowSession 方法獲取 IManagerSession 對象
首先 getWindowManagerService 方法中,通過 ServiceManager.getService("window") 方法獲得 IBinder 對象雹姊,Android Framework 與 WMS 的通信通過 Binder 機(jī)制衡楞,再通過 IManagerManager 對象的 Stub 類的 asInterface 函數(shù)將 IBinder 轉(zhuǎn)換成 IWindowManager 對象,再通過 IManagerManager 的 openSession 方法來與 WMS 建立一個長期的通信會話歧杏,需求都通過 Session 來交換信息
簡述總結(jié)一下這個過程犬绒,通過 Binder 機(jī)制獲取 IManagerSession 對象兑凿,再通過 IManagerSession 對象來跟 WMS 完成信息的交換
第四步 ViewRootImpl 的 setView 方法
在 WindowManagerGlobal 的 addView 方法中茵瘾,調(diào)用 ViewRootImpl 的 setView 方法
requestLayout View 樹的 measure layout draw 過程
sWindowSession.add() 方法咐鹤,向 WMS 發(fā)起顯示當(dāng)前 Window 的請求