Window表示一个窗口的概念,Window是一个抽象类,它的具体实现是PhoneWindow。创建一个Window,需要通过WindowManager即可完成,WindowManager是外界访问Window的入口,Window具体实现位于WindowManagerService中,WindowManager和WindowManagerService的交互是一个IPC的过程。Android中,所有的视图都是通过Window来呈现,不管是Activity、Dialog、还是Toast,它们的视图实际上都是附加在Window上,因此Window是实际View的直接管理者,单击事件由Window传递给DecorView,然后再由DecorView传递给我们的View,就连Activity的设置视图方法setContentView在底层也是通过Window来完成的。

Window和WindowManager

添加一个Window的过程,重点代码是:

mWindowManager.addView(mFLoatingButton,mLayoutParams);

WindowManager.LayoutParams中有两个flags和type参数。

Flags参数有三个Window属性

  • FLAG_NOT_FOCUSABLE。表示Window不需要获取焦点,也不需要接收各种输入事件,最终事件会直接传递给下层的具有焦点的Window
  • FLAG_NOT_TOUCH_MODAL。在此模式下,系统会将当前Window区域以外的单击事件传递给底层的Window,当前Window区域以内的单击事件则自己处理,这个标记很重要,一般来说都需要开启此标记,否则其他Window将无法收到单击事件
  • FLAG_SHOW_WHEN_LOCKED。开启此模式可以让Window显示在锁屏的界面上。

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

Window是分层的,每个Window都有对应的z-ordered,层级大的会覆盖在层级小的Window的上面,在三类Window中,应用类的Window的层级范围是1-99,子Window的层级范围是1000-1999,系统Window的层级的范围是2000-2999,这些层级范围对应着WindowManager.LayoutParams的Type参数。如想要Window位于所有Window的最顶层,那么采用较大的层级即可。很显然系统Window层级是最大的,而且系统层级有很多值。

WindowManager所提供的功能很简单,常用有三个方法,即添加View,更新View和删除View,这三个方法定义在ViewManager中,而WindowManager继承了ViewManager。

Window的内部机制

Window是一个抽象的概念,每一个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,说明View才是Window存在的实体,在实际使用中无法直接访问Window,对Window的访问必须通过WindowManager。

Window的添加过程

Window的添加过程需要通过WindowManager的addView来实现,WindowManager是一个接口,它的真正实现是WindowManagerImpl类。

@Override
public void addView(View view,ViewGroup.LayoutParams params){
mGlobal.addView(view,params,mDisplay,mParentWindow);
} @Override
public void updateViewLayout(View view,ViewGroup.LayoutParams params){
mGlobal.updateViewLayout(view,params);
} @Override
public void removeView(View view){
mGlobal.removeView(view,false);
}

可以看到,WindowManagerImpl并没有直接实现Window的三大操作,而是全部交给了WindowManagerGlobal来处理,WindowManagerGlobal以工厂的形式向外提供自己的实例。WindowManagerGlobal的addView方法主要分为如下几步:

  • 检查参数是否合法,如果是子Window那么还需要调整一些布局参数
  • 创建ViewRootImpl并将View添加到列表中
  • 通过ViewRootImpl来更新界面并完成Window的添加过程

Window的删除过程

Window的删除过程和添加过程一样,都是先通过WindowManagerImpl后,在进一步通WindowManagerGlobal来实现的。里面用到一个dispatchDetachedFromWindow方法内部实现,这个方法主要做了四件事:

  • 垃圾回收相关的工作,比如清除数据和消息、移除回调
  • 通过Session的remove方法删除Window
  • 调用View的dispatchDetachedFromWindow方法,在内部会调用View的onDetachedFromWindow()以及onDetachedFromWindowInternal()
  • 调用WindowManagerGlobal的doRemoveView方法刷新数据

Window的更新过程

主要是用到updateViewLayout方法,首先它需要更新View的LayoutParams并替换掉老的LayoutParams,接着再更新ViewRootImpl中的LayoutParams,这一步是通过ViewRootImpl的setLayoutParams方法来实现的。在ViewRootImpl中会通过scheduleTraversals方法对View进行重新布局,包括测量、布局、重绘这三个过程。

Window的创建过程

View是Android中的视图呈现方式,但是View不能单独存在,它必须附着在Window这个抽象的概念上面,因此有视图的地方就有Window。

Activity的Window创建过程

如何创建,需要了解Activity启动过程,比较复杂,但它最终由ActivityThred中的perfromLaunchActivity()来完成整个启动过程,在这个方法内部会通过类加载器创建Activity的实例对象,并调用其attach方法为其关联运行过程中所依赖的一系列上下文环境变量。

在Activity的attach方法里,系统会创建Activity所属的Window对象并为其设置回调接口,Window对象的创建是通过PolicyManager的makeNewWindow方法实现的,对于Activity的setContentView的实现可以看出,Activity将具体实现交给了Window处理,而Window的具体实现是PhoneWindow,所以只需要看PhoneWindow相关逻辑即可,大致以下几个步骤:

  • 如果没有DecorView,那么就创建它。DecorView是一个FrameLayout,是Activity的顶级View,一般来说它的内部包含标题栏和内部栏。
  • 将View添加到DecorView的mContentParent中。
  • 回调Activity的onContentChanged方法通知Activity视图已经发生改变。Activity的onContentChanged是一个空实现。

经过上面三个步骤,DecorView已经被创建初始化完毕,Activity的布局文件已经成功添加到了DecorView的mContentParent中,但是这个时候DecorView还没有被WindowManager正式添加到Window中,真正被视图调用是在Activity的onResume方法,接着会调用Activity的makeVisible(),正是在makeVisible方法中,DecorView真正地完成了添加和显示这两个过程。

Dialog的Window创建过程

Dialog的Window的创建过程和Activity类似,有以下几个步骤:

  • 创建Window。同样是通过PolicyManager的makeNewWindow方法来完成的。
  • 初始化DecorView并将Dialog的视图添加到DecorView中。
  • 将DecorView添加到Window中并显示。在Dialog的show方法中,会通过WindowManager将DecorView添加到Window中。

普通的Dialog有一个特殊之处,那就是必须采用Activity的Context,如果采用Application的Context,就会报错。

Toast的Window创建过程

Toast和Dialog不同,它的工作过程稍微复杂。首先Toast也是基于Window来实现的,但是由于Toast具有定时取消这一功能,所以系统采用了Handler。在Toast的内部有两类的IPC过程,第一类是Toast访问NotificationManagerService,第二类是NotificationManagerService回调Toast的TN接口。

Toast属于系统Window,它内部的视图有两种方式指定,一种是系统默认的样式,另一种是通过setView方法来指定一个自定义View,不管如何,它们都对应Toast的一个View类型的内部成员mNextView。Toast提供了show和cancel分别用于显示和隐藏Toast,它们的内部是一个IPC过程。

阅读扩展

源于对掌握的Android开发基础点进行整理,罗列下已经总结的文章,从中可以看到技术积累的过程。

1,Android系统简介

2,ProGuard代码混淆

3,讲讲Handler+Looper+MessageQueue关系

4,Android图片加载库理解

5,谈谈Android运行时权限理解

6,EventBus初理解

7,Android 常见工具类

8,对于Fragment的一些理解

9,Android 四大组件之 " Activity "

10,Android 四大组件之" Service "

11,Android 四大组件之“ BroadcastReceiver "

12,Android 四大组件之" ContentProvider "

13,讲讲 Android 事件拦截机制

14,Android 动画的理解

15,Android 生命周期和启动模式

16,Android IPC 机制

17,View 的事件体系

18,View 的工作原理

19,理解 Window 和 WindowManager

20,Activity 启动过程分析

21,Service 启动过程分析

22,Android 性能优化

23,Android 消息机制

24,Android Bitmap相关

25,Android 线程和线程池

26,Android 中的 Drawable 和动画

27,RecylerView 中的装饰者模式

28,Android 触摸事件机制

29,Android 事件机制应用

30,Cordova 框架的一些理解

31,有关 Android 插件化思考

32,开发人员必备技能——单元测试

理解Window和WindowManager的更多相关文章

  1. Android开发艺术探索》读书笔记 (8) 第8章 理解Window和WindowManager

    第8章 理解Window和WindowManager 8.1 Window和WindowManager (1)Window是抽象类,具体实现是PhoneWindow,通过WindowManager就可 ...

  2. 【Android开发艺术探索】理解Window和WindowManager

    个人博客: http://www.milovetingting.cn 理解Window和WindowManager Window表示一个窗口的概念,是一个抽象类,具体实现是PhoneWindow,可以 ...

  3. 第八章:理解Window和WindowManager

    Window表示一个窗口的概念. Window是一个抽象类,它的具体实现是PhoneWindow, WindowManager是外界访问Window的入口,Window的具体实现位于WindowMan ...

  4. WmS详解(二)之如何理解Window和窗口的关系?基于Android7.0源码

    上篇博客(WmS详解(一)之token到底是什么?基于Android7.0源码)中我们简要介绍了token的作用,这里涉及到的概念非常多,其中出现频率最高的要数Window和窗口这一对搭档了,那么我们 ...

  5. Activity Window View WindowManager关系&Touch事件分发机制

    http://www.cnblogs.com/linjzong/p/4191891.html https://www.cnblogs.com/kest/p/5141817.html https://b ...

  6. WmS具体解释(二)之怎样理解Window和窗体的关系?基于Android7.0源代码

    上篇博客(WmS具体解释(一)之token究竟是什么?基于Android7.0源代码)中我们简要介绍了token的作用,这里涉及到的概念非常多,当中出现频率最高的要数Window和窗体这一对搭档了,那 ...

  7. Android GUI之Window、WindowManager

    通过前几篇的文章(查看系列文章:http://www.cnblogs.com/jerehedu/p/4607599.html#gui ),我们清楚了Activity实际上是将视图的创建和显示交给了Wi ...

  8. 理解Window和WindowManger

    一.Window简介 作用:桌面上显示一个类似悬浮的东西. 介绍:Window是一个抽象类,实现是由PhoneWindow.WindowManager是外界访问Window的入口.但是最终实现是在Wi ...

  9. Android-理解window和windowmanager

    1.window和windowmanager的关系 window是一个抽象类,具体实现为phoneWindow.创建一个window可以通过windowmanager来实现. window的具体实现在 ...

随机推荐

  1. PHP安装插件方式

    PHP安装插件方法主要有两种: 1.先安装相关的库,zlib.curl.xml等,然后在安装 php 时的 ./configure 中设置 --with-xxx(你需要的插件),三部曲安装即可. 2. ...

  2. virtio-win 驱动

    Direct downloads are available for the .iso, .vfd, and qemu-ga installers. Stable virtio-win iso: ht ...

  3. [无关IT]就这样在凌晨写一篇吧~

    由于新浪博客广告实在太嚣张,自己也都是转载,故决定搬家至此,一改只转不写的习惯T^T,争取记录一下自己的小成长~日后有时间把脑子里的小东西一点点写出来~(好可怕的说)... 好了,睡了!各位爷早睡~ ...

  4. 两端对齐justify

    //容器设定text-align:justify.justify{ text-align: justify; } //容器里面的元素 .justify i{ width:24px; line-heig ...

  5. X-005 FriendlyARM tiny4412 uboot移植之时钟初始化

    <<<<<<<<<<<<<<<<<<<<<<<<< ...

  6. 【转】2015年薪酬大涨的15个IT岗位

    近日,国外科技 IT 招聘公司 Robert Half 分析了 70 个科技职位后发现 2015 年从事 IT 从业人员的平均起薪将攀升至 5.7%,其中 15 个职位的提升潜力最大. 当企业在招聘过 ...

  7. vuejs 父组件向子组件传递($broadcast()的用法)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 一个异步任务接收两个url下载两个图片

    有两个url,一个是下载用户头像的url,一个是下载用户上传图片的url,想要用一个异步任务同时下载这两个图片. 程序的下载任务是这么执行的,先接受url参数,然后调用 imgUrls = infoP ...

  9. 【Xilinx-Petalinux学习】-04-OpenCV的移植

    交叉编译PC平台 VMware12, CentOS 6.5 32 bit 在VMware中安装CentOS,用户名:xilinx-arm-opencv 密码:root 至于这里为什么用CentOS,而 ...

  10. $(function(){})和$(document).ready(function(){}) 的区别

    document.ready和onload的区别——JavaScript文档加载完成事件 页面加载完成有两种事件 一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件) 二是onloa ...