Window和WindowManager浅析

Window和WindowManager浅析

简介:
Window表示一个窗口的概念,Window是一个抽象类,它的具体实现是PhoneWindow;
通过WindowManager就可以创建Window,WindowManager是外界访问Window的入口,Window的具体实现位于WindowManagerService中,WindowManager和WMS的交互是一个IPC过程;
Android中所有的视图都是通过Window来呈现的,无论是Activity,Dialog还是Toast,它们的视图,实际上都是附加在Window上,因为Window是View的直接管理者;

1.添加窗口
WindowManager.addView(View,WindowManager.LayoutParams);
WindowManager.LayoutParams中有两个属性尤其重要,分别是flags和type;
flags参数表示Window的属性,它的选项很多,通过这些选项可以控制Window的显示特性,如:
①FLAG_NOT_FOCUSABLE
表示Window不需要获取焦点,也不需要接收各种输入事件,此标记会同时启用FLAG_NOT_TOUCH_MODAL,最终事件会直接传递给下层具有焦点的窗口;如Toast;
②FLAG_NOT_TOUCH_MODAL
此模式下,系统会将当前Window区域以外的单击事件传递给底层的Window,当前Window区域以内的单击事件则自己处理;这个标记很重要,一般来说都需要开启此标记,否则其他Window将无法收到单击事件;
③FLAG_SHOW_WHEN_LOCKED
开启此模式可以让Window显示在锁屏的页面上;

Type参数表示Winodw的类型,Window有三种类型,分别是应用Window,子Window和系统Window;
应用Window对应着一个Activity;
子Window不能单独存在,它需要附属在特定的父Window之中;比如常见的Dilaog就是一个子Window;
系统Window是需要声明权限才能创建的Window,比如Toast和系统状态栏这些都是系统Window;

Window是分层的,每个window都有对应的z-ordered,层级大的会覆盖在层级小的Window的上面;
应用类Window的层级范围是1~99,子window的层级范围是1000~1999,系统window的层级范围是2000~2900;
这些层级对应着WindowManager.LayoutParams的type参数;

注意:使用系统层级的窗口,一定要声明权限;

WindowManager所提供的方法,常用的只有三个,即添加View,更新View和删除View,这三个方法定义在WindowManager的父类ViewManager中;
ViewManager还有一个子类,便是ViewGroup,ViewGroup是来管理View的,我们也可以理解成,WindowManager是用来管理所有的窗口的;

2.Window的内部机制
每一个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,因此Window并不是实际存在的,它是以View的形式存在;
在实际应用中无法直接访问Window,对Window的访问必须是通过WindowManager;
WindowManager是一个接口,它的真正实现是WindowManagerImpl类,WindowManagerImpl又将实际操作交给WindowManagerGlobal来处理,WindowManagerGlobal是唯一的,即每个进程只有一个WindowManagerGlobal对象;

View被添加到窗口的流程:
view--->通过WindowManager--->交给了WindowManagerImpl--->WindowManagerGolbal--->创建了ViewRootImpl--->通过它的setView--->调用IWindowSession实际上是Session的addToDisplay--->WMS的addWindow,这样一个View就添加到窗口了,然后WMS通过接口与ViewRootImpl进行通讯;

3.删除窗口
删除过程会调用removeViewLocked方法,该方法通过ViewRootImpl来完成删除操作;
WindwManager中提供了两种删除接口,removeView和removeViewImmediate,分别是异步删除和同步删除;
ViewRootImpl的doDie方法内部,会调用dispatchDetachedFromWindow方法,真正删除view的逻辑在dispatchDetachedFromWindow方法内部进行了实现;
dispatchDetachedFromWindow主要做了以下事情:
①垃圾回收相关工作,比如清除数据和信息,移除回调;
②通过Session的remove方法删除Window;
③在内部调用View的onDetachedFromWindow方法,该view从Window中移除时,这个方法就会被调用,可以在方法内部做一些资源回收的工作,比如终止动画,停止线程等;

4.Window的创建过程
在Activity中,系统会创建Activity所属的Window对象并为其设置回调接口,由于Activity实现了Window的Callback接口,因此当Window接收到外界的状态改变时就会回调Activity的方法,常见的方法有:
onAttachedToWindow,onDetachedFromWindow,dispatchTouchEvent等;
PolicyManager的真正实现类是Policy类,Activity的Window是PhoneWindow;
Activity的根布局是DecorView,DecorView是一个FrameLayout,它的内部包含了标题栏和内部栏,但是这个会随着主题的变换而变换,不管怎么样,内容栏是一定要存在的,并且内容栏具体固定的id,就是content,它的完整id是android.R.id.content;

关于Activity的理解
Activity中会创建一个Window,即PhoneWindow,这个PhoneWindow用来构建DecorView,然后根据传递进来的Window属性来构建特殊的View模板,在onResume方法中会将DecorView添加到窗口;
当WindowManager或者ViewRootImpl中有变化时,如点击事件,会通过WindowManager告知Window的Callback;
Activity实现了Window的Callback接口,所以当窗口发生变化时,Activity便会得到回调;

5.Dialog的创建过程
Dialog的Window的创建过程和Acitivty类似,但是它是通过show方法,将View添加到Window中;
普通Dialog有一个特殊之处,那就是必须采用Activity的Context,如果采用Application的Context就会报错;
因为Dialog是一个子窗口类型,它需要父窗口的token,而这个父窗口即是Activity,所以它需要Activity的context作为构造参数;

注意,系统Window比较特殊,它可以不需要token,但是系统窗口需要声明;

6.Toast的Window创建过程
Tost提供了show和cancel分别用于显示和隐藏Toast;
由于Toast内部使用了Handler,这就意味着Toast无法在没有Looper的线程中弹出;
 

转载于:https://my.oschina.net/u/3491256/blog/1546221

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值