Android中與ViewRoot相關的一些概念
1、View和ViewRoot
ViewRoot從名稱上來理解似乎是“View樹的根”,這很容易讓人產生誤解。因為ViewRoot並不屬於View樹的一份子。從源碼實現上來看,ViewRoot和View對象並沒有任何“血緣”關係,它既非View的子類,也非View的父類。ViewRoot可以被理解為“View樹的管理者”——它有一個mView成員變數,指向的是它所管理的View樹的根。
咱們看下下面的布局代碼:
上面的布局代碼只是一份任意的布局代碼,這裡主要看下其結構,該布局代碼的View結構可以描如下:
在該布局中,ViewRoot中的mView成員變數指向的就是它所管理的View樹的根,即中的LinearLayout:test元素。ViewRoot的核心任務就是與WindowManagerService進行通訊。 2、Activity和Window的關係 我們知道Activity是支援顯示UI的,那麼它是否直接管理view樹或者ViewRoot呢?答案時否定的,Activity並沒有與這兩者產生直接的聯絡,因為這中間還有一個被稱為“Window”的對象。大家可以在Activity的源碼中找到如下代碼:private Window mWindow; Window的字面意思是視窗,這很好地解釋了它存在的意義。Window是基類,根據不同的產品可以衍生出不同的子類——具體則是由系統在Activity.attach中調用PolicyManager.makeNewWindow決定的,目前版本的Android系統預設產生的都是PhoneWindo。 3、Window和WindowManagerImpl的關係 在Android源碼中以“Window”開頭的類有不少,如Window,WindowManager,WindowManagerImpl等,為什麼需要這麼多相似的類呢? 先來看Window,它是面向Activity的,表示UI介面的外框;而“框裡面”具體的東西包括布局和內容等,是由具體的Window子類,如PhoneWindow來規劃的。 Window的另一層含義是要與WindowManagerService進行通訊,但它並沒有直接在自身實現這一功能。原因是:一個應用程式中很可能存在多個Window。如果它們都單獨與WMS通訊,那麼既浪費資源,又會造成管理的混亂。換句話說,它們需要統一的管理。於是就有了WindowManager,它作為Window的成員變數mWindowManager存在。這個WindowManager是一個介面類,其真正的實現是WindowManagerImpl,後者同時也是整個應用程式中所有Window的管理者。因而WindowManager與WindowManagerImpl的關係有點類似於“地方與中央”:地方為實施中央的“政策”提供了一個介面,然後匯總到中央進行管理。 在Window的源碼中與mWindowMager有關的代碼有如下幾句:private WindowManager mWindowManager; mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
public WindowManager getWindowManager() {
return mWindowManager;
}
然後我們去WindowManagerImpl的代碼中去查看createLocalWindowManager方法的代碼,代碼如下:
public WindowManagerImpl createLocalWidnowManager(Window parentWindow) {
return new WindowManagerImpl(mDisplay, parentWindow);
}
從這幾處代碼,大家可以看到Window類中的mWindowManger引用的其實是WindowManagerImpl的執行個體。
4、ViewRoot和WindowManagerImpl的關係
在早期的系統版本中,WindowManagerImpl在每個進程中只有一個執行個體。調用它必須使用如下語句:WindowManagerImpl.getDefault();
在WindowMangerImpl內部,存在3個全域變數:(中的源碼是2.3.5中的)
它們分別用於表示View樹的根節點、ViewRoot以及Window的屬性。由此也可以看出,一個進程中不僅有一個ViewRoot;而Activity與ViewRoot則是一對一的關係。自Android4.3開始對此做了修改,WindowManagerImpl不再直接儲存上述三個陣列變數,而是由一個稱為“WindowMangerGlobal”的類統一管理。 5、ViewRoot和WindowManagerService的關係 每一個ViewRootImpl內部,都有一個全域變數 static IWindowSession sWindowSession; 這個變數用於ViewRoot到WMS的串連,它是ViewRoot利用WMS的openSession()介面來建立得到的。在此基礎上,ViewRoot也會通過IWindowSession.add()方法提供一個IWindow對象——從而讓WMS也可以通過這個IBinder對象來與ViewRoot進行雙向通訊。 這裡突然間冒出一個ViewRootImpl類,其實ViewRoot與ViewRootImpl的功能是一樣的,只不過是Android不同版本的不同稱呼。不信看:
既然說到這個圖了,那麼就在這裡給大家推薦一個可以線上看Android源碼的網站:http://grepcode.com/project/repository.grepcode.com/java/ext/com.google.android/android/ 其實每個Application都有一個ActivityThread主線程以及mActivities全域變數,後者記錄了運行在應用程式中的所有Activity對象。一個Activity對應唯一的WindowManager以及ViewRootImpl。WindowManagerGlobal作為全域管理者,其內部的mRoots和mViews記錄了Activity的ViewRootImpl和View樹的頂層元素。ViewRootImpl的另一個重要角色就是負責與WMS通訊。從ViewRootImpl到WMS間的通訊利用的是IWindowSession,而反方向則是由IWindow來完成的。 最後補充說明一點:Activity中有一個成員變數mWindow,mWindow裡面有一個成員變數mWindowManager,而mWindowManager是WindowMangerImpl類執行個體的引用,另外WindowMangerImpl裡麵包含ViewRoot(不管老版本中直接包含,還是新版本中間接包含)。 本篇博文只是為了記錄我對於ViewRoot以及與ViewRoot相關的一些概念的瞭解。