Window 和 WindowManager
2016-07-16 本文已影响229人
日三省
这篇文章是本着抛砖引玉的目的,如果有不严谨,甚至错误地方,劳驾各位指正。
有一群很(hua)好(qian)学(mai)的粉丝问,Window和WindowManager是什么东西,我就去查资料了。
说到这得吐槽一下。
一开始,我只想知道window是什么东西,每!一!篇!文章都说,window是一个抽象的东西,抽象的东西...然后就没有了。抽象xxx啊抽象!难道哪天面试官问我,window是什么?我就回答说,window是个很抽象的东西?
并且,那些文章都无一例外的又臭又长,没看一会儿就不由得生出一种,“这孙子在说什么?”,的感觉。
OK,说正事。
首先,谈谈Window到底是啥。它是一个很抽象的东西。
拿明星来举例子:
有的明星是单独发展的,比如周杰伦,如果我们碰到他会怎么喊他呢,直接喊“周杰伦”对不对。
有的明星是以组合形式发展的,并且分工不同,比如五月天,他们有主唱、有键盘、有二胡、有三弦儿...如果碰到五月天我们会怎么喊呢,应该没人傻到会把几位成员的名字连起来挨个喊一遍吧?这时候,“五月天”是对多个人的总称。
同理,window也是一个组合,成员分别是View和ViewRootImpl。View是颜值担当,是给大家看的。ViewRootImpl是劳动担当,是干活的,比如更新View。(这样理解不知是否严谨)
概念弄明白后就看一下流程。
调用流程原谅我图画的很糙。
- 竖直方向是类的继承关系,水平方向是方法的调用流程。被框起来的是各个类里面的方法。相信通过方法名也能看得出怎么调用的吧。
- ViewManager中定义了常用的三个方法,addView、updateViewLayout、removeView,即添加View、更新View和删除View
- WindowManager是个接口,实现它是WindowManagerImpl。所以,图中WindowManagerImpl的三个方法是从ViewManager继承来的。
- WindowManagerImpl和WindowManagerGlobal三个方法长得一模一样,这里使用的桥接模式,意思就是,分配给WindowManagerImpl干的工作,被它原封不动的转给勤劳的WindowManagerGlobal对象干了。
- ViewRootImpl,待会再说
- IPC调用,说明WindowManagerService是运行在其他进程的
分情况分析一下调用流程,直接从WindowManagerGlobal开始:
- 添加View
Window这个“组合”是在Global的addView方法里被创建的。
addView过程中,会new一个ViewRootImpl对象和View“绑定”,用来操作View。并且,在Global对象中有专门的数据结构来存储View,和与之对应的ViewRootImpl和LayoutParams,以便以后可查。
接下来,ViewRootImpl对象的addView会被调用,最后,通过它的一个成员变量,Session对象,完成对WindowManagerService中addView的跨进程调用。
Session为什么有如此神通?
因为Session实现了IWindowSession,而IWindowSession正是一个Binder对象。 - 删除View
同理,跨进程调用还是通过Session。
唯一需要说明的就是,ViewRootImpl里面有两个remove相关的方法:removeView和removeViewImmediate。
两者区别是:
- 前者是异步删除,方法内部只发送了一个MSG_DIE的消息就返回了,ViewRootImpl的handler会处理该消息并调用doDie方法
- 后者是同步删除,方法不发消息,直接调用doDie方法
- 更新View
没什么需要说的,从头到尾走下来就是。