第八章 理解Window和WindowManager

Window是一个抽象类,它的具体是现实PhoneWindow,通过WindowManager就可以创建Window。WindowManager是外界访问Window的入口,但是Window的具体实现是在WindowManagerService中,WindowManager和WindowManagerService的交互是一个IPC的过程。所有的视图例如Activity、Dialog、Toast都是附加在Window上的。

8.1 Window和WindowManager

(1). 通过WindowManager添加View 的过程:将一个Button添加到屏幕坐标为(100,300)的位置上。

mFloatingButton = new Button(this);
mFloatingButton.setText("test button");
mLayoutParams = new WindowManager.LayoutParams(LaytouParams.WRAP_CONTENT,LaytoutParams.WRAP_CONTENT,0,0,PixelFormat.TRANSPARENT);//0,0,分别是type和flags参数,在后面分别配置了。
mLaytouParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_SHOW_WHEN_LOCKED;
mLayoutParams.type = LayoutParams.TYPE_SYSTEM_ERROR;
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayoutParams.x = 100;
mLayoutParams.y = 300;
mFloatingButton.setOnTouchListener(this);
mWindowManager.addView(mFloatingButton, mLayoutParams);

flags参数解析:
FLAG_NOT_FROUSABLE:表示window不需要获取焦点,也不需要接受各种输入事件。此标记会同时启用FLAG_NOT_TOUCH_MODAL,最终事件会直接传递给下层的具有焦点的window;
FLAG_NOT_TOUCH_MODAL:在此模式下,系统会将window区域外的点击事件传递给底层的window,当前window区域内的点击事件则自己处理,一般都需要开启这个标记,否则其他的Window将无法收到点击事件。
LayoutParams.FLAG_SHOW_WHEN_LOCKED:开启此模式可以让Window显示在锁屏的界面上。

type参数表示window的类型,window共有三种类型:应用window,子window和系统window。应用window对应着一个Activity,子window不能独立存在,需要附属在特定的父window之上,比如Dialog就是子window。系统window是需要生命权限才能创建的window,比如Toast和系统状态栏这些都是系统window,需要声明的权限是<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
(2). window是分层的,每个window都对应着z-ordered,层级大的会覆盖在校的上面,应用window的层级范围是1~99,子window的层级范围是1000~1999,系统window的层级范围是2000~2999
(3). 如果想要Window位于所有的Window的最顶层,那么采用较大的层级即可。很显然系统Window的层级是最大的,而且系统层级有很多值,一般我们可以选用TYPE_SYSTEM_VIERLAY或者TYPE_SYSTEM_ERROR,如果采用TYPE_SYSTEM_ERROR,只需要为type参数指定这个层级即可:mLayoutParams.type = LayoutParams.TYPE_SYSTEM_ERROR;同时声明权限:<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
WindowManager所提供的功能很简单,常用的只有三个方法,即添加View、更新View和删除View。

8.2 Window的内部机制

(1). Window是一个抽象的概念,不是实际存在的,它也是以View的形式存在。在实际使用中无法直接访问Window,只能通过WindowManager才能访问Window。
(2). Window的添加过程:Window的添加过程需要通过WindowManageraddView来实现,WindowManager是一个接口,它的真正实现是WindowManagerImpl类。在源码中,WindowManagerImpl并没有直接实现Window的三大操作,而是全部交给了WindowManagerGlobal。

8.3 Window的创建过程

View是Android中的视图的呈现方式,但是View不能单独存在,它必须附着在Window这个抽象的概念上面,因此有视图的地方就有Window,我们平常使用的Activity、Dialog、Toast还有PopUpWindow和菜单都对应着一个Window。
(1). Activity的window创建过程
1. Activity的启动过程很复杂,最终会由ActivityThread中的performLaunchActivity来完成整个启动过程,在这个方法内部会通过类加载器创建Activity的实例对象,并调用它的attach方法为其关联运行过程中所以来的一系列上下文环境变量;
2. Activity实现了Window的Callback接口,当window接受到外界的状态变化时就会回调Activity的方法,例如onAttachedToWindowonDetachedFromWindowdispatchTouchEvent等。
3. Activity的Window是由PolicyManager来创建的,它的真正实现是Policy类,它会新建一个PhoneWindow对象,Activity的setContentView的实现是由PhoneWindow来实现的。
4. Activity的顶级View是DecorView,它本质上是一个FrameLayout。如果没有DecorView,那么PhoneWindow会县创建一个DecorView,然后加载具体的布局文件并将view添加到DecorView的mContentParent中,最后就是毁掉Activity的onContentChanged通知Activity视图已经发生了变化。
5. 还有一个步骤是让WindowManager能够识别DecorView,在ActivityThread调用handleResumeActivity方法时,首先会调用Activity的onResume方法,然后会调用makeVisible方法,这个方法中DecorView真正地完成了添加和显示过程。

ViewManager vm = getWindowManager();
vm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;

(2). Dialog的Window创建过程
过程与Activity的Window创建过程类似,普通的Dialog有一个特别之处,即它必须采用Activity的Context,如果采用Application的Context会报错。原因是Application没有应用token,应用token一般是只有Activity才拥有。ps:service也没有token,所以也不能在service中弹出dialog,但是使用系统的Window指定对话框,不需要使用token

dialog.getWindow().getType(LayoutParams.TYPE_SYSTEM_ERROR);

(3). Toast的Window创建过程
1. Toast属于系统Window,它内部的视图由两种方式指定:一种是系统默认的样式;另一种通过setView方法来指定一个自定义的View。
2. Toast具有定时取消功能,所以系统采用了Handler。Toast的显示和隐藏是IPC过程,都需要NotificationManagerService来实现。在Toast和NMS(NotificationManagerService)进行IPC过程时,NMS会跨进程回调Toast中的TN类中的方法,TN类是一个Binder类,运行在Binder线程池镇南关,所以需要通过Handler将其切换到当前发送Toast请求所在的线程,所以Toast无法再没有Looper的线程中弹出。
3. 对于非系统引用来说,mToastQueue最多能同事存在50个ToastRecord,这样做是为了防止DOS(Denial of Service,拒绝服务)。因为如果某个应用弹出太多的Toast会导致其他应用没有机会弹出Toast。

【Anroid界面实现】WindowManager类使用详解——用户首次打开APP的使用教学蒙板效果实现

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值