Window和WindowManager
標(biāo)簽(空格分隔): android
一些簡單的定義:
- WindowManager是外界訪問Window的入口(相當(dāng)于代理人),window的具體實現(xiàn)位于WindowManagerService中,WindowManager和WindowManagerService的交互是一個IPC過程。
- android中所有的視圖都是tongguowindow呈現(xiàn)出來的,Window是是view的直接管理者,它會將事件傳遞給頂層View--DecorView。
WindowManager添加一個Window
mWindowManager.addView(mButton,mLayoutParams);
- 值得一說的東西:WindowManage.layoutParams的兩個參數(shù)----flags和type。
- Flag表示W(wǎng)indow的屬性。
1、FLAG_NOT_FOCUSABLE:window不獲取焦點,不接受各種輸入事件,事件傳遞給下層具有焦點的window。
2、FLAG_NOT_TOUCH_MODAL:系統(tǒng)會將當(dāng)前Window區(qū)域以外的點擊事件傳遞給底層的Window,當(dāng)前的window區(qū)域內(nèi)的點擊事件則自己處理。
3、FLAG_SHOW_WHEN_LOCKED:讓window顯示在鎖屏的頁面上。
- Flag表示W(wǎng)indow的屬性。
- Type是window的類型,應(yīng)用window(對應(yīng)一個Activity)、子window(需要依附一個父window)、系統(tǒng)window(toast等)。
- window的z-ordered
1、應(yīng)用window的層級范圍是199,子window層級范圍是10001999,系統(tǒng)window層級范圍是2000~2999.
2、層級越大優(yōu)先級越大。
Window內(nèi)部機(jī)制
簡單介紹:
每一個window都對應(yīng)一個view和viewRootImpl,window和view通過viewRootImpl建立聯(lián)系,window的訪問必須通過windowManager。
window的添加過程
其實對window的操作是以下的流程:
windowManager---》windowManagerImpl---》windowManagerGlobal
大致流程如下:
1、檢查參數(shù)是否合法,如果有子window那么還需要一些布局參數(shù)。
2、創(chuàng)建ViewRootImpl并將View添加到列表。WindowManagerGlobal內(nèi)部有幾個列表,分別是View、ViewRootImpl、mparams、待刪除的View列表。
3、通過ViewRootImpl來更新頁面并完成Window的添加過程。
大致流程:setView(ViewRootImpl)-->scheduleTraversals(requestLayout)-->windowSession(Binder對象)-->addToDisplay(IPC調(diào)用)--> windowManagerService
4、通過WindowManagerService進(jìn)行Window的添加。
window的刪除過程
和window的添加過程一樣,最終實現(xiàn)都是在windowManagerGlobal實現(xiàn)的(具體方法就是removeView)。
- removeView的邏輯:首先通過findViewLocked來查找待刪除的View索引(就是數(shù)組的遍歷),然后通過調(diào)用removeViewLocked來做進(jìn)一步的刪除。
-
removeViewLocked的內(nèi)部實現(xiàn):
- dispatchDetachedFromWindow的功能:
- 垃圾回收相關(guān)工作,如清理數(shù)據(jù)等。
- 通過Session的remove方法刪除Window,一個IPC過程。
- 通過View的dispatchDetachedFromWindow方法,在內(nèi)部會調(diào)用View的onDetachedFromWindow,主要用于資源回收。
- 調(diào)用WindowManagerGlobal的doRemoveView方法刷新數(shù)據(jù),更新前面所說的列表。
window的更新,就不詳說了,大概流程和前面兩個差不多。(開發(fā)探索P304)
一些重要的Window
Activity的Window創(chuàng)建過程
- window的創(chuàng)建實現(xiàn)是在Activity的attach方法里面,系統(tǒng)會創(chuàng)建Activity所屬的Window對象并為其回調(diào)接口,Window對象的創(chuàng)建是通過PolicyManager的makeNewWindow方法實現(xiàn)。
- Policy的真正實現(xiàn)是Policy類,Policy類的makeNewWindow方法,其實具體實現(xiàn)是PhoneWindow。
- 所以讓我們一起來看看PhoneWindow的setContentView方法:
- 如果沒有DecorView,就創(chuàng)建它。(installDecor--->generateDecor(這個方法直接創(chuàng)建DecorView))
- 將View添加到DecorView的mContentParent中。
- 回調(diào)Activity的onCreateChanged方法通知Activity視圖發(fā)生變化。(handleResumeActivity-->onResume-->makeVisible)
Dialog的Window創(chuàng)建過程
1、創(chuàng)建Window。
2、初始化DecorView并將Dialog的視圖添加到DecorView中。
3、將DecorView添加到Window中并顯示
4、Dialog被銷毀時,通過WindowManager來移除DecorView:removeViewImmediate。
特殊之處:必須采用Activity的上下文Context
Toast的Window創(chuàng)建過程
- Toast內(nèi)部有兩類IPC過程,第一類是Toast訪問NMS(NotificationManagerService),第二類是NMS回掉Toast里面的TN接口。
- 由于Toast的隱藏和顯示會涉及到跨進(jìn)程調(diào)度,需要用到TN接口,TN接口其實現(xiàn)是Binder線程池,需要Handler切換線程,所以Toast不能在沒有Looper的線程中使用。(詳見消息機(jī)制)。
- Toast的顯示:
NMS中的enqueueToast方法(第一個參數(shù)是包名,第二個參數(shù)是tn,第三個參數(shù)是toast顯示的時長)---將Toast封裝成一個ToastRecord對象,然后添加到mToastQueue隊列里面。 ---》 NMS中的showNextToastLocked方法顯示當(dāng)前Toast(其調(diào)度是一個IPC過程,) ---》NMS的scheduleTimeoutLocked方法(發(fā)送一條延時消息,取決于Toast的時長) ---》 NMS中的cancelToastLocked方法隱藏Toast并將其從mToastQueue移除(出隊列,同樣也是IPC調(diào)用)。
總結(jié):
一個Window對應(yīng)一個View。
其調(diào)度是一個IPC過程,需要用到消息機(jī)制,即Handler。