android的窗口機制分析——ViewRoot類

ViewRoot是GUI管理系統與GUI呈現系統之間的橋梁,根據ViewRoot的定義,我們發現它並不是一個View類型,而是一個Handler。
 
它的主要作用如下:
 
A. 向DecorView分發收到的用戶發起的event事件,如按鍵,觸屏,軌跡球等事件;
 
B. 與WindowManagerService交互,完成整個Activity的GUI的繪制。
 
 
 
    事件處理和GUI繪制的具體實現在後面的文章中再描述,這篇文章就主要介紹ViewRoot對象如何同WindowManagerService橋接起來的。   
 
    在完成Activity的ContentView設置之後,下面的工作就是準備顯示瞭,準備顯示的主要工作就是建立起Application和WindowManagerService之間的聯系,第一步的工作就是向WindowManager添加前面涉及到的DecorView,我們已經知道這個DecorView包含瞭整個Activity的GUI,所以我們隻需要把這個DecorView交給WindowManager打理就可以瞭。
 
    下面看看整個的過程   
 
A.     向WindowManager添加DecorView;
 
 
handleResumeActivity@ActivityThread.java
 
 
[java]
r.window = r.activity.getWindow(); 
View decor = r.window.getDecorView(); 
decor.setVisibility(View.INVISIBLE); 
ViewManager wm = a.getWindowManager(); 
WindowManager.LayoutParams l = r.window.getAttributes(); 
a.mDecor = decor; 
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 
l.softInputMode |= forwardBit; 
if (a.mVisibleFromClient) { 
    a.mWindowAdded = true; 
    wm.addView(decor, l); 

 
 
 
B.WindowManagerImpl保存DecorView到mViews,創建對應的ViewRoot;
 
 
 
C.調用ViewRootsetView()方法
 
 
這個方法中的主要工作就是建立起與WindowManagerService之間的聯系。
[java]
requestLayout(); 
try { 
    res = sWindowSession.add(mWindow, mWindowAttributes, 
            getHostVisibility(), mAttachInfo.mContentInsets); 
} catch (RemoteException e) { 
 
在這個方法中隻需要關註兩個步驟
 
(1)   requestLayout()
 
    請求WindowManagerService繪制GUI,但是註意一點的是它是在與WindowManagerService建立連接之前繪制,為什麼要在建立之前請求繪制呢?
 
    其實兩者實際的先後順序是正好相反的,與WMS建立連接在前,繪制GUI在後,那麼為什麼代碼的順序和執行的順序不同呢?這裡就涉及到ViewRoot的屬性瞭,我們前面提到ViewRoot並不是一個View,而是一個Handler,那麼執行的具體流程就是這樣的:
 
a)       ActivityThread的handler函數註冊瞭啟動一個新的Activity的請求處理LAUNCH_ACTIVITY,LAUNCH_ACTIVITY的處理過程調用到瞭ViewRoot的setView()方法,因此上圖代碼在被執行時正處於LAUNCH_ACTIVITY消息的處理過程中。
 
b)       requestLayout()其實是向messagequeue發送瞭一個請求繪制GUI的消息,並且ViewRoot和ActivityThread共用同一個MessageQueue(如下圖),因此繪制GUI的過程一定是在LAUNCH_ACTIVITY消息被處理完之後,也就是sWindowSessoin.add()方法調用完之後。
 
 
(2)   sWindowSessoin.add()
 
從字面意思理解的話,IWindowSession sWindowSessoin是ViewRoot和WindowManagerService之間的一個會話層,它的實體是在WMS中定義,作為ViewRoot requests WMS的橋梁。
 
add()方法的第一個參數mWindow是ViewRoot提供給WMS,以便WMS反向通知ViewRoot的接口。由於ViewRoot處在application端,而WMS處在system_server進程,它們處在不同的進程間,因此需要添加這個IWindow接口便於GUI繪制狀態的同步。
 

摘自 杜文濤的專欄

發佈留言