Android的Window和WindowManager

来源:互联网 发布:大数据相关课程 编辑:程序博客网 时间:2024/06/09 19:46

       在日常开发中直接接触Window的机会并不多,但是比如我们需要在界面显示一个类似悬浮窗的东西时,这种效果就需要用到Window来实现。Window实际上是一个抽象类,他的具体实现是PhoneWindow,位于WindowManagerService中。创建Window是通过WindowManager实现的,WindowManager实际上是外界访问Window的入口。而WindowManagerService和WindowManager的交互实际上是一个IPC(跨进程通信Inter-Process-Communication)过程。Android中不管Activity、Toast、Dialog等所有视图都是通过Window呈现的,也就是附加在Window上。所以Window其实是View的直接管理者。那前面博文讲的Activity设置视图的方法setContentView在底层其实也是通过Window来完成的。Window的功能更多是底层的支持,所以开发并不常用。

1.   Window和WindowManager

      要明白Window的工作机制,不如先从如何使用Windowmanager添加一个Window说起。

      Eg:Button  button  =  new Button (this);

              LayoutParams  layoutParams  =  new  WindowManager.LayoutParames(……);

              layoutParames.flags =

              LayoutParames.FLAG_NOT_TOUCH_MODAL|LayoutParames.FLAG_NOT_FOUCESABLE|                                                              LayoutParames.FLAG_SHOW_WHEN_LOCKED;

              layoutParames.gravity = Gravity.LEFT|Gravity.TOP;

              layoutParames.x = 100;

               layoutParames.y = 300;

              mWindowManager.addView ( button , layoutParams );

       上述代码使把一个Buton添加到屏幕坐标未(100,300)的位置上。其中WindowManager.LayoutParames的type和flags两个参数比较重要。Flags控制Window的显示特性。type参数表示Window的类型,Window一共三种类型:应用Window,子Window和系统Window。应用Window对应一个Activity,子Window只能附属在特定的父Window中,比如Dialog就是一个子Window。而Toast就是一个系统Window。同时Window是分层的,层级大区的覆盖在层级小的Window上面,所以可见系统Window的层级大于子Window,子Window的层级大于应用Window。这些层级对应的就是上面提到的type参数。如果type使用系统层级,一定要记得在AndroidManifest.xml中声明权限。

<uses-permissionandroid:name= “android.permission.SYSTEM_ALERT_WINDOW”/>.

        WindowManager提供的方法很简单,常用的也就三个:添加View,删除View和更新View。这三个方法定义在ViewManager中,WindowManager继承了ViewManager。

2.  Window的内部机制

        准确来讲Window并不是实际存在的,他依托于View的形式存在,View才是Window存在的实体,两者通过ViewRootImpl建立联系。  View的绘制过程由ViewRootImpl的setView方法完成的.实际使用中使无法直接访问Window的,对Window的访问必须是通过WindowManager才能完成

        Window的添加过程:

        Window的添加通过WindowManager的addView实现。WindowManager实际是一个接口,他的实现是WindowManagerImpl,WindowManagerImpl又将Window的三大操作交给了WindowManagerGlobal。WindowManagerGlobal中维护的列表中有几个比较重要的:

mView:所有Window对应的View;

mParams:所有Window所对应的布局参数;

mDyingViews:正在被删除的View对象;

      Window的删除过程:

     和添加过程一样,底层都是先通过WindowManagerImpl后,在经由WindowManagerGlobal来实现的。在WindowManager中提供了removeView和removeViewImmediate两个删除接口,分别表示异步删除和同步删除。使用后者可能会发生意外的错误,一般不需要使用。

      Window的更新过程:

      通过WindowManagerGlobal中的updateViewLayout完成。该方法做的比较简单,先是用新的LayoutParams替换掉ViewRootImpl中旧的LaouyParams,在ViewRootImpl中通过scheduleTraversals对View重新布局。最终是由WindowManagerervice的relayoutWindow()来具体实现,所以可见又是一个IPC过程。

3.  Window的创建过程

       View虽然使Android中视图的呈现方式,但又不能独立存在,必须依附于Window这个抽象的概念上面。所以有视图的地方就一定有Window。Android中的Activity,Toast,Dialog,Menu其实都对应着一个Window。

       先简述一下Activity中Window的创建过程:Activity启动过程很复杂,但最终会由ActivityThread中的performLaunchActivity()来完成启动过程,这个方法中会启用类加载器创建Activity的实例对象,并调用attach方法为Activity关联运行过程中将依赖的一系列上下文环境变量。attach方法中系统会创建其所属的Window并设置回调接口,Window对象的创建由PolicyManager的makeNewWindow实现,这是一个工厂方法。

        Window mWindow = PolicyManager.makeNewWindow(this);

        那再看看Activity的视图使怎么依附于Window上的。Activity中setContentView的源码如下:

 public void setContentView(intlayoutResID){

       getWindow().setContentView(layoutResID);

       initWindowDecorActionBar();

}

       所以可以看出Activity将视图的具体实现交给了Window,Window的具体实现是PhoneWindow。所以视图的创建是在PhoneWinow中的setContentView()中完成的。DecorView是Activity中的顶级View,首先会创建一个DecorView,不过是一个空的FrameLayout,然后PhoneWindow加载布局文件到这个FrameLayout。因为Activity实现了Window的Callback接口,所以这时就回到Activity的onContentChanged方法通知Activity视图已经发生变化。经过上面三个步骤,Activity的DecoeView已经被创建并初始化完毕。前面已经说了Activity的attach方法中Window已经被创建了,但DecorView还没被添加到Window中,所以无法接受外界输入。在ActivityThread的handleResumeActivity方法中,首先调用Activity的Resume方法,接着调用Activity的makeVisible(),在这个方法中真正完成了DecorView的添加和显示的过程。这是Activity的视图才能被用户看到。

        Toast的Window相对复杂一点,因为他是系统Window,显然涉及到IPC。Toast涉及两类IPC过程:第一类是NotificationManagerService(NMS),第二类是NotificationManagerService回调Toast的TN接口,这个接口运行在Binder线程池中,他提供了show和cancle两个方法将Toast的视图添加到Window中,完成Toast的显示和隐藏。NMS中的enqueueToast方法首先将Toast请求封装成ToastRecord对象并添加到队列mToastQueue中。之后NMS通过内置方法,由ToastRecord的callback回调完成。这个回调就是前面提到的TN对象的远程Binder,为了切换到Toast请求所在的线程,在他们的内部使用了Handler。同理,Dialog的Window的创建过程和Activity是类似的。介绍到这里很清楚了,就是任何View都是附属在一个Window上面的。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我的信息被泄露怎么办 进入不良网站手机发信息怎么办 发不良信息被停机了怎么办 手机qq登录显示被冻结怎么办 qq账户被冻结了怎么办 qq钱包账户被永久冻结怎么办 怎么办转让费还没给我 收钱吗不能抵用红包怎么办 红包抵扣被关了怎么办 天猫客户给差评怎么办 淘宝闪电退款有纠纷怎么办呀 手机屏幕右下角出现彩色点怎么办 在超市买到假货怎么办 天猫超市多发货怎么办 天猫中不小心取消退款了怎么办 天猫超市写错了怎么办 二维码收付款不到红包怎么办 天猫优惠劵过期了怎么办 天猫购物津贴用不完怎么办 天猫上买的大件东西实物不符怎么办 天猫上面料成分与实物不符怎么办 闲鱼发货与实物不符怎么办 天猫超市买贵了怎么办 天猫超市里购买的东西退货怎么办 淘宝店上传的图片不清楚怎么办 微信图片打印出来不清楚怎么办 微信图片打印不清楚怎么办 淘宝上传商品视频不清楚怎么办 手机安装器没了怎么办 我不做直播换工作怎么办 天猫发票被投诉怎么办 天猫机顶盒闪退怎么办 苹果8红色掉漆怎么办 毛坯房验房房及厅试水时漏水怎么办 淘宝退货赠品被拆了怎么办 如果淘宝买家说赠品不好怎么办 淘宝顾客反应没赠品怎么办 淘宝上买东西赠品不给怎么办 天猫店关了质量有问题怎么办 蘑菇街开店被骗了怎么办 百视通网络机顶盒恢复出厂后怎么办