Window与WMS通信过程

我的CSDN博客同步发布:Window与WMS通信过程

转载请注明出处:【huachao1001的简书:http://www.jianshu.com/users/0a7e42698e4b/latest_articles】

上一篇文章【理清Activity、View及Window之间关系】我们大致知道了Window的绘制过程,但是比较笼统,本文主要介绍Window对象与(后面缩写为WMS)之间是如何通信。毫无疑问,肯定是通过IPCBinder机制),这点肯定都知道,但是我们要学习是的是,哪些类参与了IPC调用过程。另外,本文没有研究源码,而是通过阅读其他研究源码的文章,然后总结出来,以更容易理解的方式展示。本文设计到的相关资料在文章最后一一列出。

1 Window添加的大致过程

Window的添加过程需要通过WindowManageraddView来实现,WindowManager是一个接口,真正的实现是WindowManagerImpl。而WindowManagerImpl全部是转移给WindowManagerGlobal来处理,WindowManagerImpl这种工作模式是典型的桥接模式。WindowManagerImpl内三大操作过程如下:

public void addView(View view,ViewGroup.LayoutParams params){
    mGlobal.addView(view,params,mDisplay,mParantWindow);
}

public void updateViewLayout(View view,ViewGroup.LayoutParams params){
    mGlobal.updateViewLayout(view,params);
}

public void removeView(View view){
    mGlobal.removeView(view,false);
}

WindowManagerGlobal名称可以看出,它是一个全局的WindowManager,其内部维护如下几个列表:

private final ArrayList<View> mViews = new ArrayList<View>();
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>()
private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.layoutParams>();
private final ArraySet<View> mDyingViews = new ArraySet<View>();

其中:

  • mViews:存储所有Window所对应的View
  • mRoots:存储的是所有Window所对应的ViewRootImpl
  • mParams:存储的是所有Window所对应的布局参数
  • mDyingView:存储了那些正在被删除的View对象,或者说是那些已经调用了removeView方法但是删除操作还未完成的Window对象。

addView中通过如下方式将Window的一系列对象添加到列表中:

root=new ViewRootImpl(view.getContext(),display);
view.setLayoutParams(wparams);

mViews.add(view);
mRoots.add(root);
mParams.add(wparams);

可以看到,到目前为止,只是把相应的对象存放到ArrayList列表中。后面还需要将View给显示出来。绘制View需要通过ViewRootImplsetView方法来实现。在setView内部是通过requestLayout来完成一部刷新请求的。

public void requestLayout(){
    if(!mHandlingLayoutInlayoutRequest){
        checkThread();
        mLayoutRequested=true;
        scheduleTraversals();
    }
}

其中scheduleTraversalsView绘制的入口!

下面我们看看ViewRootImpl是内部机制。

2 ViewRootImpl内部机制

ViewRootImpl用于管理窗口的根View,并和WMS进行交互。ViewRootImpl中有一个内部类: W,以及另一个内部类:ViewRootHandler

  • W继承自IWindow.Stub。是一个Binder对象,用于接收WMS的各种消息, 如按键消息, 触摸消息等。

  • ViewRootHandler,是Handler的子类, W会通过Looper把消息传递给ViewRootHandler

ViewRootImpl有一个W类型的成员mWindowViewRootImpl在构造函数中创建一个W的实例并赋值给mWindow

ViewRootImplsetView方法(此方法运行在UI线程)中,会通过IPC的方式跨进程向WMS发起一个远程调用,从而将DecorView最终添加到Window上,在这个过程中,ViewRootImplDecorViewWMS会彼此向关联.

另外,WMS有时也需要向ViewRootImpl发送远程请求,比如,点击事件是由用户的触摸行为所产生的,因此它必须要通过硬件来捕获,跟硬件之间的交互自然是Android系统自己把握,Android系统将点击事件交给WMS来处理。WMS通过远程调用将事件发送给ViewRootImpl,在ViewRootImpl中,有一个方法,叫做dispatchInputEvent,最终将事件传递给DecorView

3 Window与WMS之间的双向通信

接下来,由WindowSession来完成最后的Window添加过程。mWindowSession本身是一个IWindowSession类型对象,通过内部代理类Proxy访问远程Session类(Binder机制) 。在Session内部通过WMS来实现Window的添加。如此一来Window的添加请求就交给了WMS去处理了,如下图所示:

ViewRootImpl与WmS之间通信
ViewRootImpl与WmS之间通信

WindowManagerService内部为每个应用保留一个单独的Session,如下图所示:

每个应用对应一个Session

前面我们说过,每个Window对应一个ViewRootImpl及一个View Tree。也就是说,每个Activity对应的Window(一个或多个)内通过其内置的ViewRootImpl完成向WMS的请求过程。

一个应用中的所有Activity共用一个Session,一个WindowWMS内部对应一个WindowStateWindowState维护窗口的状态以及根据适当的机制来调整窗口的状态。

如果一个Activity多个Window,如对话框、Popup类型、或者通过ViewManagerView直接加入WMS,等等。在这些情况下,一个Activity就会创建多个Window,相应的WMS中也会对应多个WindowState,如下图所示:

多个Window情况下对应关系

4 WMS控制窗口的显示



以下内容来自老罗的的博客,后面附有资料链接。

WMS服务大致按照以下方式来控制哪些窗口需要显示的以及要显在哪里:

  1. 每一个Activity窗口的大小都等于屏幕的大小,因此,只要对每一个Activity窗口设置一个不同的Z轴位置,然后就可以使得位于最上面的,即当前被激活的Activity窗口,才是可见的。

  2. 每一个子窗口的Z轴位置都比它的父窗口大,但是大小要比父窗口小,这时候Activity窗口及其所弹出的子窗口都可以同时显示出来。

  3. 对于非全屏Activity窗口来说,它会在屏幕的上方留出一块区域,用来显示状态栏。这块留出来的区域称对于屏幕来说,称为装饰区(decoration),而对于Activity窗口来说,称为内容边衬区(Content Inset)。

  4. 输入法窗口只有在需要的时候才会出现,它同样是出现在屏幕的装饰区或者说Activity窗口的内容边衬区的。

  5. 对于壁纸窗口,它出现需要壁纸的Activity窗口的下方,这时候要求Activity窗口是半透明的,这样就可以将它后面的壁纸窗口一同显示出来。

  6. 两个Activity窗口在切换过程,实际上就是前一个窗口显示退出动画而后一个窗口显示开始动画的过程,而在动画的显示过程,窗口的大小会有一个变化的过程,这样就导致前后两个Activity窗口的大小不再都等于屏幕的大小,因而它们就有可能同时都处于可见的状态。事实上,Activity窗口的切换过程是相当复杂的,因为即将要显示的Activity窗口可能还会被设置一个启动窗口(Starting Window)。一个被设置了启动窗口的Activity窗口要等到它的启动窗口显示了之后才可以显示出来。

参考资料:

  1. 【Android窗口管理服务WindowManagerService的简要介绍和学习计划 】
  2. 《Android开发艺术探索》
  3. 【Android 应用程序建立与WMS服务之间的通信过程】
  4. 【Android Window Manager Subsystem Research 】
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容