《android开发艺术探索》读书笔记(八)--WindowManager
No1:
Window是一个抽象类,它的具体实现是PhoneWindow。创建一个Window是很简单的事,只需要通过WindowManager即可完成。
WindowManager是外界访问Window的入口,Window的具体实现位于WindowManagerService中,WindwoManager和WindowManagerService的交互时一个IPC过程。
Android中所有的视图都是通过Window来呈现的,因此Window实际是View的直接管理者。
单机事件由Window传递给DecorView,然后再由DecorView传递给我们的View。
No2:
Window有三种类型,分别是应用Window、子Window和系统Window。
应用Window--一个Activity
子Window--不能单独存在,需要附属在特定的父Window中,比如Dialog
系统Window--是需要声明权限才能创建的Window,比如Toast和系统状态栏
No3:
Window是分层的,每个Window都有对应的z-ordered,层级大的会覆盖在层级小的Window的上面。
应用层Window层级范围1~99
子Window层级范围1000~1999
系统Window层级范围2000~2999
这些层级范围对应着WindowManager.LayoutParams的type参数。如果想要Window位于所有Window的最顶层,那么采用较大的层级即可。
No4:
WindowManager所提供的功能很简单,常用的只有三个方法,添加ViewaddView、更新ViewupdateViewLayout和删除ViewremoveView,这三个方法定义在ViewManager中,而WindowManager继承了ViewManager。
No5:
可以拖动的Window效果
public boolean onTouch(View v,MotionEvent event){
int rawX = (int)event.getRawX();
int rawY = (int)event.getRawY();
switch(event.getAction()){
case MotionEvent.ACTION_MOVE:
mLayoutParams.x = rawX;
mLayoutParams.y = rawY;
mWindowManager.updateViewLayout(mFloationButton,mLayoutParams);
break;
default:
break;
}
return false;
}
No6:
Window是一个抽象的概念,每个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立连接,因此Window并不是实际存在的,它是以View的形式存在。
在实际使用中无法直接访问Window,对Window的访问必须通过WindowManager。
No7:
WindowManager是一个接口,它的真正实现是WindowManagerImpl类。WindowManagerImpl并没有直接实现Window的三大操作,而是全部交给了WindowManagerGlobal来处理。
WindowManagerImpl这种工作模式是典型的桥接模式。
No8:
Window的添加过程
WindowManagerImpl.addView-->
WindowManagerGlobal.addView-->
mViews.add-->
ViewRootImpl.setView-->requestLayout-->scheduleTraversals-->
WindowSession.addToDisplay-->
Session.addToDisplay-->
WindowManagerService.addWindow-->
1.检查参数是否合法,如果是子Window那么还需要调整一些布局参数
2.创建ViewRootImpl并将View添加到列表中
3.通过ViewRootImpl来更新界面并完成Window的添加过程
View的绘制过程是由ViewRootImpl来完成的,在setView内部会通过requestLayout完成异步刷新请求,scheduleTraversals实际是View绘制的入口,接着会通过WindowSession最终来完成Window的添加过程,真正的实现类是Session,也就是Window的添加过程是一次IPC调用,在Session内部会调用WindowManagerService来实现Window的添加。
No9:
Window的删除过程
WindowManagerImpl.removeView-->
WindowManagerGlobal.removeView-->
WindowManagerGlobal.removeViewLocked-->
ViewRootImpl.die-->
ViewRootImpl.doDie-->
ViewRootImpl.dispatchDetachedFromWindow-->
WindowManager中提供了两种删除接口removeView和removeViewImmediate,分别表示异步删除和同步删除。
异步删除具体的删除操作由ViewRootImpl的die方法来完成,die发送了一个请求删除的消息,ViewRootImpl中的Handler会处理此消息并调用doDie方法,如果是同步删除,那么就不发消息直接调用doDie方法。
doDie内部会调用dispatchDetachedFromWindow方法,dispatchDetachedFromWindow主要做四件事:
1)垃圾回收相关工作,比如清除数据和消息、移除回调
2)通过Session的remove方法删除Window:mWindowSession.remove(mWindow),这同样是一个IPC过程,最终会调用WindowManagerService的removeWindow方法
3)调用View的dispatchDetachedFromWindow方法,在内部会调用View的onDetachedFromWindow()以及onDetachedFromWindowInternal()。
当View从Window中移除时,这个方法就会被调用,可以在这个方法内部做一些资源回收的工作,比如终止动画、停止线程等
4)调用WindowManagerGolbal的doRemoveView方法刷新数据,包括mRoots、mParams以及mDyingViews,需要将当前Window所关联的这三类对象从列表中删除。
No10:
Window的更新过程:还是要看WindowManagerGlobal的updateViewLayout方法:
1)通过ViewRootImpl的setLayoutParams更新View的LayoutParams并替换掉老的LayoutParams,接着再更新ViewRootImpl中的LayoutParams
2)在ViewRootImpl中会通过scheduleTraversals方法来对View重新布局,包括测量、布局、重绘这三个过程
3)ViewRootImpl还会通过WindowSession来更新Window视图,最终是由WindowManagerService的relayoutWindow()来具体实现的。同样是一个IPC过程
No11:
Window对象的创建是通过PolicyManager的makeNewWindow方法实现的。PolicyManager的真正实现是Policy类,所以Window的具体实现的确是PhoneWindow。
No12:
setContentView:Activity-->Window-->PhoneWindow
No13:
DecorView是一个FrameLayout,是Activity中的顶级View,一般包括标题栏和内部栏
No14:
Activity的Window的创建过程
ActivityThread.performLaunchActivity-->
PhoneWindow的setContentView步骤
1)如果没有DecorView,那么就创建它
2)将View添加到DecorView的mContentParent中(这就是为Activity的setContentView而不叫setView的缘由)
3)回调Activity的onContentChanged方法通知Activity视图已经发生改变
No15:
在ActivityThread的makeVisible()方法中,首先会调用Activity的onResume方法,接着会调用Activity的makeVisible(),正是在makeVisible方法中,DecorView真正地完成了添加和显示这两个过程,到这里Activity的视图才能被用户看到。
No16:
Dialog的Window创建过程
PolicyManager.makeNewWindow-->
Window.setContentView-->
WindowManager.addView-->
1)创建Window
2)初始化DecorView并将Dialog的视图添加到DecorView中
3)将DecorView添加到Window中并显示
No17:
普通Dialog有一个特殊之处,就是必须采用Activity的Context,如果采用Application的Context,会报错没有token,而应用token一般只有Activity拥有。
系统Window不需要token,因此只要指定对话框为Window为系统类型即可
No18:
Toast具有定时取消这一功能,所以系统采用了Handler。
Toast内部有两类IPC过程,第一类是Toast访问NotificationManagerService,第二类是NotificationManagerService回调Toast里面的TN接口。
显示和隐藏Toast都需要通过NotificationManagerService来实现,因为NMS运行在系统进程中,所以只能通过远程调用的方式来显示和隐藏。TN是一个Binder类,它运行在Binder线程池中,所以需要Handler将其切换到当前线程中,这里的当前线程是指发送Toast请求所在的线程。
No19:
enqueueToast首先将Toast请求封装为ToastRecord对象并将其添加到一个名为mToastQueue的队列中。mToastQueue其实是一个ArrayList。对于非系统应用来说,mToastQueue中最多能同时存在50个ToastRecord。如果不这样做,将导致其他引用没有机会弹出Toast。
No20:
Toast延时相应时间后,NotificationManagerService会通过cancelToastlocked方法来隐藏Toast并将其从mToastQueue中移除,这个时候如果mToastQueue中还有其他Toast,那么NMS就继续显示其他Toast。Toast的隐藏也是通过ToastRecord的callback来完成的,这同样也是一次IPC过程。
No21:
Toast中TN的两个方法show和hide,是以NMS以跨进程的方式调用的,因此它们运行在Binder线程池中。
《android开发艺术探索》读书笔记(八)--WindowManager的更多相关文章
- Android开发艺术探索读书笔记——01 Activity的生命周期
http://www.cnblogs.com/csonezp/p/5121142.html 新买了一本书,<Android开发艺术探索>.这本书算是一本进阶书籍,适合有一定安卓开发基础,做 ...
- Android开发艺术探索读书笔记——进程间通信
1. 多进程使用场景 1) 应用某些模块由于特殊需求须要执行在单独进程中. 如消息推送,使消息推送进程与应用进程能单独存活,消息推送进程不会由于应用程序进程crash而受影响. 2) 为加大一个应用可 ...
- android开发艺术探索读书笔记之-------view的事件分发机制
View的点击事件的分发,其实就是对MotionEvent事件的分发过程,即当一个MotionEvent产生后,系统需要把这个事件传递给一个具体的View,而这个过程就是分发过程. 分发过程主要由以下 ...
- Android开发艺术探索学习笔记(四)
第四章 View的工作原理 4.1初识ViewRoot和DecorView ViewRoot是连接WindowManager和DecorView的纽带,View的三大流程均是通过ViewRoot来完成 ...
- Android开发艺术探索学习笔记(三)
第三章 View的事件体系 3.1 View基础知识 3.1.1 什么是view View 是Android中所有控件的基类,是一种界面层的控件的一种抽象,它代表了一个控件. 3.1.2 View的 ...
- Android开发艺术探索学习笔记(十一)
第十一章 Android的线程和线程池 从用途上来说,线程分为子线程和主线程,主线程主要处理和界面相关的事情,而子线程往往用于执行耗时的操作.AsyncTask,IntentService,Hand ...
- Android开发艺术探索学习笔记(十)
第十章 Android的消息机制 面试中经常会被问到的一个问题:handler是如何在子线程和主线程中进行消息的传递的,这个问题通过了解Android的消息机制可以得到一个准确的答案. Androi ...
- Android开发艺术探索学习笔记(六)
第六章 Android的Drawable Drawable的优点:使用简单,比自定义view的成本要低:非图片类型的Drawable占用空间小,有利于减小APK安装包的大小. 6.1Drawable ...
- Android开发艺术探索学习笔记(一)
第一章 Activity的生命周期和启动模式 1.1Activity的生命周期全面解析 1.1.1典型情况下的生命周期分析 (1)在两个Activity进行切换时,当前的Activity的onPaus ...
- 《Android开发艺术探索》读书笔记 (9) 第9章 四大组件的工作过程
第9章 四大组件的工作过程 9.1 四大组件的运行状态 (1)四大组件中只有BroadcastReceiver既可以在AndroidManifest文件中注册,也可以在代码中注册,其他三个组件都必须在 ...
随机推荐
- keytool 错误:java.to.FileNotFoundException:
老是报如题的错误: 后来才知道是因为当前的目录下没有写的权限,所以需要指定一个路径来存放android.key: keytool -genkey -alias android.key -keyalg ...
- 浅谈最大流的Dinic算法
PART 1 什么是网络流 网络流(network-flows)是一种类比水流的解决问题方法,与线性规划密切相关.网络流的理论和应用在不断发展,出现了具有增益的流.多终端流.多商品流以及网络流的分解与 ...
- 布隆过滤器(BloomFilter)持久化
摘要 Bloomfilter运行在一台机器的内存上,不方便持久化(机器down掉就什么都没啦),也不方便分布式程序的统一去重.我们可以将数据进行持久化,这样就克服了down机的问题,常见的持久化方法包 ...
- JAVA设计模式---装饰者模式
写在前面的话: 该模式动态的将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案.装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的 ...
- vue2使用高德地图vue-amap定位以及AMapUI标注
前言 最近在vue里使用了高德地图vue-amap以及AMapUI,我在这里就说下如何在vue2里引入vue-amap和AmapUI以及使用定位 (在这里默认你已经安装了vue-cli) 安装 npm ...
- NIO内存映射
磁盘的IO因为速度较慢,可能成为系统运行的瓶颈.所以磁盘的IO在操作系统级实现了提前读,延迟写的机制来提升IO的性能. 提前读就是一次读取需求的数据的同时多读接下来的一段数据至OS缓冲区中,延迟写就是 ...
- BZOJ 3091: 城市旅行 [LCT splay 期望]
3091: 城市旅行 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1454 Solved: 483[Submit][Status][Discuss ...
- 简单实现ASP.Net MVC网页播放音乐
<div> @*音乐*@ <audio id="warning-sound" loop="loop" src="/Areas/Map ...
- python 闯关之路一(语法基础)
1,什么是编程?为什么要编程? 答:编程是个动词,编程就等于写代码,那么写代码是为了什么呢?也就是为什么要编程呢,肯定是为了让计算机帮我们搞事情,代码就是计算机能理解的语言. 2,编程语言进化史是什么 ...
- 「POJ2505」A multiplication game [博弈论]
题目链接:http://poj.org/problem?id=2505 题目大意: 两个人轮流玩游戏,Stan先手,数字 p从1开始,Stan乘以一个2-9的数,然后Ollie再乘以一个2-9的数,直 ...