android的視窗機制分析------ViewRoot類

yangxi_001發表於2014-02-21

    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] view plaincopy
  1. r.window = r.activity.getWindow();  
  2. View decor = r.window.getDecorView();  
  3. decor.setVisibility(View.INVISIBLE);  
  4. ViewManager wm = a.getWindowManager();  
  5. WindowManager.LayoutParams l = r.window.getAttributes();  
  6. a.mDecor = decor;  
  7. l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;  
  8. l.softInputMode |= forwardBit;  
  9. if (a.mVisibleFromClient) {  
  10.     a.mWindowAdded = true;  
  11.     wm.addView(decor, l);  
  12. }  



B. WindowManagerImpl儲存DecorView到mViews,建立對應的ViewRoot;


C.呼叫ViewRootsetView()方法


這個方法中的主要工作就是建立起與WindowManagerService之間的聯絡。

[java] view plaincopy
  1. requestLayout();  
  2. try {  
  3.     res = sWindowSession.add(mWindow, mWindowAttributes,  
  4.             getHostVisibility(), mAttachInfo.mContentInsets);  
  5. 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繪製狀態的同步。

相關文章