Android中与ViewRoot相关的一些概念

1、View和ViewRoot

ViewRoot从名称上来理解似乎是“View树的根”,这很容易让人产生误解。因为ViewRoot并不属于View树的一份子。从源码实现上来看,ViewRoot和View对象并没有任何“血缘”关系,它既非View的子类,也非View的父类。ViewRoot可以被理解为“View树的管理者”——它有一个mView成员变量,指向的是它所管理的View树的根。

咱们看下下面的布局代码:
<pre name="code" class="html"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
	 android:id="@+id/test"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
	<Button 
	    android:id="@+id/start_service"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:text="Start Service"
	    />
	<Button 
	    android:id="@+id/stop_service"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:text="Stop Service"
	    />
	<Button 
	    android:id="@+id/bind_service"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:text="Bind Service"
	    />
	<Button 
	    android:id="@+id/unbind_service"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:text="Unbind Service"
	    />

</LinearLayout>



上面的布局代码只是一份任意的布局代码,这里主要看下其结构,该布局代码的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;
 public WindowManager getWindowManager() {
技术分享
         return ;
     }

然后我们去WindowManagerImpl的代码中去查看createLocalWindowManager方法的代码,代码如下:
 
 public WindowManagerImpl createLocalWidnowManager(Window parentWindow) {
技术分享
技术分享
        return new WindowManagerImpl(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相关的一些概念的了解。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。