Window和WindowManager

参考资料

凯子哥带你学Framework· Activity界面显示全解析-上
凯子哥带你学Framework Activity界面显示全解析-下
重要:!!! Android 屏幕刷新机制


目录

  • 1)简介
  • 2)Window的内部机制
    • 2.1)Window的添加过程
    • 2.2)Window的删除过程
    • 2.3)Window的更新过程
  • 3)Window的创建过程
    • 3.1)Activity的Window创建过程
    • 3.2)Dialog的Window创建过程
    • 3.3)Toast的Window创建过程

1)简介

  • Window是一个抽象类,具体实现为PhoneWindow
  • 只需要WindowManager即可创建一个Window
  • WindowManager是个接口,是外界访问Window的入口,具体实现位于WindowManagerService(WMS),WindowManager和WindowManagerService的交互是一个IPC过程
  • Android所有视图都是附加在Window上,通过Window来呈现,因此Window是View的直接管理者。如事件分发就是通过Window传递给DecorView。
  • 站在系统角度,Window代表一块显示区域,系统并不关心Window内的绘制内容
//WindowManager可以通过下面两种方式进行获取
WindowManager mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 
WindowManager mWindowManager = (WindowManager) getWindowManger();
//WindowManager添加一个Window
mWindowManager.addView(mButton, mLayoutParams); 

2)Window的内部机制

Window是以View的形式存在,View的绘制流程从ViewRoot开始,ViewRoot对应ViewRootImpl类,它是连接WindowManager和DecorView的纽带。

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

->ViewManager.addView
->WindowManager.addView(也是接口,继承ViewManager)
->WindowManagerImpl.addView(实现了WindowManager接口)
->WindowManagerGlobal.addView(接受WindowManagerImpl的委托,并构建ViewRootImpl)
->ViewRootImpl.setView(ViewRooImpl是WindowManagerGlobal的addView方法中新建的对象)
->requestLayout(setView中的一个方法调用,调用performTraversals绘制整个view树)
->WindowSession.addToDisplay(在setView方法中,它是一个Binder对象,用于与WindowManagerService进行IPC通信)
->Session(WindowSession的具体实现)
->WindowManagerService(实现Window的添加)

ViewRootImpl负责管理视图树和与WMS交互,它是WindowManager和DecorView的纽带,与WMS交互是通过WindowSession。而且ViewRootImpl也负责UI界面的布局与渲染,负责把一些事件分发至Activity,以便Activity可以截获事件。大多数情况下,它管理Activity顶层视图DecorView,它相当于MVC模型中的Controller。


3)Window的创建过程

3.1)Activity的Window创建过程

Activity 四大组件之一, 是存放View对象的容器,也是我们界面的载体,可以用来展示一个界面。它有一个SetContentView()方法 ,可以将我们定义的布局设置到界面上
View 就是一个个视图的对象
Window 抽象类,是一个顶层的窗口,它的唯一实例是PhoneWindow它提供标准的用户界面策略,如背景、标题、区域,默认按键处理等

Activity就像是一扇贴着窗花的窗口,Window就想上窗口上面的玻璃,而View对象就像一个个贴在玻璃上的窗花。

  • Activity最终会由ActivityThread中的performLaunchActivity来完成启动,此方法内会通过类加载器创建Activity的实例对象,并调用attach关联所依赖的上下文。
  • 在attach方法中,系统会创建Activity所属的Window对象,并获取了WindowManager对象。
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);/设置回调函数,使得Activity可以处理一些事件,如dispatchTouchEvent()
  • setContentView()调用了Window的setContentView(),将界面绘制交给了Window对象,也就是View通过Activity添加到了Window上面。
    • DecorView是PhoneWindow的内部类,继承自FrameLayout,是最底层的界面
    • 如果没有DecorView,则创建它
    • 将View添加到DecorView的mContentParent对象中
    • 回调Activity的onContentChanged()通知Activity视图已改变
  • 经过上面步骤DecorView已初始化,且Activity的布局也被添加到了DecorView的mContentParent对象中。但这时DecorView还没有被WindowManager添加到Window中,
void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

在Activity的onResume()中,WindowManager会执行addView(mDecorView,getWindow().getAttributes())。至此Activity的视图才能被用户看见。

20151028131646957.png

3.2)Dialog的Window创建过程

AlertDialog和Activity一样,内部有一个Window,我们构造AlertDialog.Builder,通过Builder设置Dialog各种属性,,这些参数会被放在一个名为P(AlertController类型)的变量中,在调用AlertDialog.Builder.create方法的时候,内部首先会new一个 AlertDialog,AlertDialog的父类Dialog的构造函数中会new一个PhoneWindow赋值给AlertDialog中的Window,并且为它设置了回调。AlertDialog创建之后执行apply方法,将P中的参数设置赋值给Dialog,后我们调用Dialog.show方法展示窗口,内部调用dispatchOnCreate,最终会走到setContentView,到此Dialog的Window和Dialog视图关联到了一起,最后执行mWindowManager.addView方法,通过WindowManager将DecorView添加到Window之中,此时Dialog显示在了我们面前。

  • 在Activity中使用Dialog的时候,为什么有时候会报错“Unable to add window -- token is not valid; is your activity running?”?
    答:
    一般发生在Activity进入后台,Dialog没有主动Dismiss掉,然后从后台再次进入App的时候。
    Window分为三种,子窗口,应用窗口和系统窗口,子窗口必须依附于一个上下文,就是Activity,因为它需要Activity的appToken,
    子窗口的window,比如Dialog,想要显示必须保证appToken与Activity保持一致,当Activity销毁,再次回来的时候,Dialog试图重新创建,调用ViewRootImpl的setView()的时候会出问题,所以当Activity不可见的时候,主动Dismiss掉Dialog,否则会因为appToken为空crash。
  • 在子线程中为什么不能显示Toast?
    Toast源码是与NotificationManagerService进行IPC通信,
    show()的时候,通过handler来接收,子线程中没有handler,所以无法显示。可以给子线程添加Looper
sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
  • 为什么不能在setContentView()之后设置某些Window属性标志?
public void setContentView(View view) {
        getWindow().setContentView(view);
        initWindowDecorActionBar();//初始化window属性
}

在Activity.setContentView()之后,Window的一些特征位将被锁定

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

推荐阅读更多精彩内容