Window和WindowManager

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顯示在鎖屏的頁面上。
  • 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。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容