前言

WindowManagerService(WMS)和AMS一样,都是Android开发需要掌握的知识点,同样的,WMS也很复杂,需要多篇文章来进行讲解,为何更好的理解WMS,首先要了解WindowManager,这一篇我们来学习WindowManager体系。

1.Window、WindowManager和WMS

Window我们应该很熟悉,它是一个抽象类,具体的实现类为PhoneWindow,它对View进行管理。 WindowManager是一个接口类,继承自接口ViewManager,从名称就知道它是用来管理Window的,它的实现类为WindowManagerImpl。如果我们想要对Window进行添加和删除就可以使用WindowManager,具体的工作都是由WMS来处理的,WindowManager和WMS通过Binder来进行跨进程通信,WMS作为系统服务有很多API是不会暴露给WindowManager的,这一点与ActivityManager和AMS的关系有些类似。
关于WMS的功能,会在后续文章进行介绍,这里我们只需要知道它的主要功能包括Window管理和输入系统就可以了。这一系列文章的重点是WindowManager。
Window、WindowManager和WMS的关系可以简略的用下图来表示。

Window包含了View并对View进行管理,Window用虚线来表示是因为Window是一个抽象概念,并不是真实存在,Window的实体其实也是View。WindowManager用来管理Window,而WindowManager所提供的功能最终会由WMS来进行处理。

2.WindowManager体系

接下来我们从源码角度来分析WindowManager体系以及Window和WindowManager的关系。
WindowManager是一个接口类,继承自接口ViewManager,ViewManager中定义了三个方法,分别用来添加、更新和删除View:
frameworks/base/core/java/android/view/ViewManager.java

public interface ViewManager
{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}

WindowManager也继承了这些方法,而这些方法传入的参数都是View,说明WindowManager具体管理的是以View形式存在的Window。WindowManager在继承ViewManager的同时,又加入很多功能,包括Window的类型和层级相关的常量、内部类以及一些方法,其中有两个方法是根据Window的特性加入的,如下所示。

public Display getDefaultDisplay();
public void removeViewImmediate(View view);

getDefaultDisplay方法会得知这个WindowManager实例将Window添加到哪个屏幕上了,换句话说,就是得到WindowManager所管理的屏幕(Display)。removeViewImmediate方法则规定在这个方法返回前要立即执行View.onDetachedFromWindow(),来完成传入的View相关的销毁工作。关于Window的类型和层级会在本系列后续的文章进行介绍。
Window是一个抽象类,它的具体实现类为PhoneWindow。在Activity启动过程中会调用ActivityThread的performLaunchActivity方法,performLaunchActivity方法中又会调用Activity的attach方法,如果不了解这些请查看Android深入四大组件(一)应用程序启动过程(后篇)这篇文章。
我们从Activity的attach方法开始入手,如下所示。
frameworks/base/core/java/android/app/Activity.java

final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window);//
...
/**
*2
*/
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != );
...

注释1处创建了PhoneWindow,在注释2处调用了PhoneWindow的setWindowManager方法,这个方法的具体的实现在PhoneWindow的父类Window中。
frameworks/base/core/java/android/view/Window.java

public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);//
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);//
}

如果传入的WindowManager为null,就会在注释1处调用Context的getSystemService方法,并传入服务的名称Context.WINDOW_SERVICE(”window”),具体的实现在ContextImpl中,如下所示。
frameworks/base/core/java/android/app/ContextImpl.java

@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
} @Override
public String getSystemServiceName(Class<?> serviceClass) {
return SystemServiceRegistry.getSystemServiceName(serviceClass);
}

最终会调用SystemServiceRegistry的getSystemServiceName方法。
frameworks/base/core/java/android/app/SystemServiceRegistry.java

public static String getSystemServiceName(Class<?> serviceClass) {
return SYSTEM_SERVICE_NAMES.get(serviceClass);
}

SYSTEM_SERVICE_NAMES是一个HashMap类型的数据,它用来存储服务的名称,那么传入的Context.WINDOW_SERVICE到底对应着什么?我们接着往下看。
frameworks/base/core/java/android/app/SystemServiceRegistry.java

final class SystemServiceRegistry {
...
private SystemServiceRegistry() { }
static {
...
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher<WindowManager>() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx);
}});
...
}
}

SystemServiceRegistry 的静态代码块中会调用多个registerService方法,这里只列举了和本文有关的一个。registerService方法会将传入的服务的名称存入到SYSTEM_SERVICE_NAMES中。从上面代码可以看出,传入的Context.WINDOW_SERVICE对应的就是WindowManagerImpl实例,因此得出结论,Context的getSystemService方法得到的是WindowManagerImpl实例。我们再回到Window的setWindowManager方法,在注释1处得到WindowManagerImpl实例后转为WindowManager类型,在注释2处调用了WindowManagerImpl的createLocalWindowManager方法:

frameworks/base/core/java/android/view/WindowManagerImpl

public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mContext, parentWindow);
}

createLocalWindowManager方法同样也是创建WindowManagerImpl,不同的是这次创建WindowManagerImpl时将创建它的Window作为参数传了进来,这样WindowManagerImpl就持有了Window的引用,就可以对Window进行操作,比如
在Window中添加View,来查看WindowManagerImpl的addView方法:
frameworks/base/core/java/android/view/WindowManagerImpl

@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);//
}

注释1处调用了WindowManagerGlobal的addView方法,其中最后一个参数mParentWindow就是Window,可以看出WindowManagerImpl虽然是WindowManager的实现类,但是却没有实现什么功能,而是将功能实现委托给了WindowManagerGlobal,这里用到的是桥接模式。关于在Window中添加View,本系列后续的文章会详细介绍。
我们来查看WindowManagerImpl中如何定义的WindowManagerGlobal:
frameworks/base/core/java/android/view/WindowManagerImpl

public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
private final Context mContext;
private final Window mParentWindow;//
...
private WindowManagerImpl(Context context, Window parentWindow) {
mContext = context;
mParentWindow = parentWindow;
}
...
}

可以看出WindowManagerGlobal是一个单例,说明在一个进程中只有一个WindowManagerGlobal实例。注释1处说明WindowManagerImpl可能会实现多个Window,也就是说在一个进程中WindowManagerImpl可能会有多个实例。

通过如上的源码分析,Window和WindowManager的关系如下图所示。

PhoneWindow继承自Window,Window通过setWindowManager方法与WindowManager发生关联。WindowManager继承自接口ViewManager,WindowManagerImpl是WindowManager接口的实现类,但是具体的功能都会委托给WindowManagerGlobal来实现。

Android解析WindowManager(一)WindowManager体系的更多相关文章

  1. Android解析WindowManager(三)Window的添加过程

    前言 在此前的系列文章中我们学习了WindowManager体系和Window的属性,这一篇我们接着来讲Window的添加过程.建议阅读此篇文章前先阅读本系列的前两篇文章. 1.概述 WindowMa ...

  2. Android解析WindowManager(二)Window的属性

    前言 在上一篇文章我们学习了WindowManager体系,了解了Window和WindowManager之间的关系,这一篇我们接着来学习Window的属性. 1.概述 上一篇文章中我们讲过了Wind ...

  3. Android 之 Window、WindowManager 与窗口管理

    其实在android中真正展示给用户的是window和view,activity在android中所其的作用主要是处理一些逻辑问题,比如生命周期的管理.建立窗口等.在android中,窗口的管理还是比 ...

  4. 我的Android进阶之旅------>WindowManager.LayoutParams介绍

    本文转载于: http://hubingforever.blog.163.com/blog/static/171040579201175111031938/ 本文参照自: http://develop ...

  5. Android WindowManager和WindowManager.LayoutParams的使用以及实现悬浮窗口的方法

    1.理清概念 我们使用过Dialog和PopupWindow,还有Toast,它们都显示在Activity之上.那么我们首先需要理解的是android中是如何去绘制这些UI的呢?这里我只讲我所理解的, ...

  6. Android解析WindowManagerService(三)Window的删除过程

    前言 在本系列文章中,我提到过:Window的操作分为两大部分,一部分是WindowManager处理部分,另一部分是WMS处理部分,Window的删除过程也不例外,本篇文章会介绍Window的删除过 ...

  7. Android解析WindowManagerService(二)WMS的重要成员和Window的添加过程

    前言 在本系列的上一篇文章中,我们学习了WMS的诞生,WMS被创建后,它的重要的成员有哪些?Window添加过程的WMS部分做了什么呢?这篇文章会给你解答. 1.WMS的重要成员 所谓WMS的重要成员 ...

  8. WindowManager和WindowManager.LayoutParams的使用以及实现悬浮窗口的方法

    写Android程序的时候一般用WindowManager就是去获得屏幕的宽和高,来布局一些小的东西.基本上没有怎么看他的其他的接口. 这两天想写一个简单的类似于Toast的东西,自定义布局,突然发现 ...

  9. Window WindowManager 和WindowManager.LayoutParams

    <一> Window window是android中的窗口,表示顶级窗口的意思,也就是主窗口,它有两个实现类, PhoneWindow和MidWindow,我们一般的activity对应的 ...

  10. android解析XML总结(SAX、Pull、Dom三种方式) <转载>

    android解析XML总结(SAX.Pull.Dom三种方式) http://www.cnblogs.com/JerryWang1991/archive/2012/02/24/2365507.htm ...

随机推荐

  1. python使用(五)

    1.shell_option.py 2.db_option.py 1.shell_option.py # coding=utf8 __author__ = 'SummerChill' import o ...

  2. Android开发艺术探索学习笔记(六)

    第六章 Android的Drawable  Drawable的优点:使用简单,比自定义view的成本要低:非图片类型的Drawable占用空间小,有利于减小APK安装包的大小. 6.1Drawable ...

  3. 06 - JavaSE之常用类

    String类 String 类是不可变的字符序列,String 字符串一旦分配好就不能改变其内容和长度了.(如果使用 s1+=s2; 并不是在s1的后面开辟空间将s2拷贝其内,而是另外开辟一个空间, ...

  4. js便签笔记(6)——jQuery中的ready()事件为何需要那么多代码?

    前言: ready()事件的应用,是大家再熟悉不过的了,学jQuery的第一步,最最常见的代码: jQuery(document).ready(function () { }); jQuery(fun ...

  5. 和我一起打造个简单搜索之ElasticSearch集群搭建

    我们所常见的电商搜索如京东,搜索页面都会提供各种各样的筛选条件,比如品牌.尺寸.适用季节.价格区间等,同时提供排序,比如价格排序,信誉排序,销量排序等,方便了用户去找到自己心里理想的商品. 站内搜索对 ...

  6. PTA (Advanced Level) 1004 Counting Leaves

    Counting Leaves A family hierarchy is usually presented by a pedigree tree. Your job is to count tho ...

  7. APIX招聘

  8. Spring事务内方法调用自身事务 增强的三种方式

    ServiceA.java文件: 查看Spring Tx的相关日志:  可以看到只创建了一个事物ServiceA.service方法的事务,但是callSelf方法却没有被事务增强; 分析原因:Spr ...

  9. Java设计模式学习记录-抽象工厂模式

    前言 上篇博客介绍了简单工厂模式和工厂方法模式,这次介绍抽象工厂模式,抽象工厂模式和工厂方法模式的区别在于需要创建对象的复杂程度上. 抽象工厂模式 抽象工厂模式是围绕着一个超级工厂创建其他工厂.这个超 ...

  10. 基于vue实现一个简单的MVVM框架(源码分析)

    不知不觉接触前端的时间已经过去半年了,越来越发觉对知识的学习不应该只停留在会用的层面,这在我学jQuery的一段时间后便有这样的体会. 虽然jQuery只是一个JS的代码库,只要会一些JS的基本操作学 ...