前言
在Android视图体系中Window就是一个窗口的概念。Android中所有的视图都是依赖于Window显示的,比如:Activity、Dialog、Toast都是在Window中显示的。
首先来熟悉一下Window的属性。
Window的类型:
- 应用Window:即Android应用所在的Window,比如Activity对应的Window;
- 子Windwo:必须依赖于应用Window存在,比如:Dialog;
- 系统Window:系统级别的Window,比如系统错误窗口、Toast。
Windwo的ZOrder属性,ZOrder主要是在屏幕Z轴的数值,主要用来表示Window的层级,数值大的显示在屏幕上层。其中应用Window的数值范围是199;子Window的数值范围是10001999;系统Window的数值范围是2000~2999。
Window的标志:
Flag | 描述 |
---|---|
FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | 只要窗口可见,就允许在开启状态上的屏幕上锁屏 |
FLAG_NOT_FOCUSABLE | 窗口不需要获取焦点,也不需要接收输入事件,设置的同时FLAG_NOT_TOUCH_MODAL也会被设置 |
FLAG_NOT_TOUCH_MODAL | 该窗口只会处理自己区域内的点击事件,区域外的事件将传递给其他窗口 |
FLAG_NOT_TOUCHABLE | 窗口不接受任何触摸事件 |
FLAG_KEEP_SCREEN_ON | 只要窗口可见,屏幕保持常亮 |
FLAG_LAYOUT_NO_LIMITS | 允许屏幕超出窗口之外 |
FLAG_FULLSCREEN | 窗口全屏显示,隐藏所有屏幕的装饰窗口 |
FLAG_SHOW_WHEN_LOCKED | 窗口可以显示在锁屏窗口中 |
FLAG_IGNORE_CHEEK_PRESSES | 当用户的脸贴近屏幕时,不会响应此事件 |
FLAG_TURE_SCREEN_ON | 窗口显示是将屏幕点亮 |
窗口机制
在日常开发中,我们通常接触到关于窗口的类有WindowManager和Window。在查看两者的源码时,可以看到WindowManager是一个接口,Window是一个抽象类。其中WindowManager继承了ViewManager接口,ViewManager中定义了三个方法。
public interface ViewManager
{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
可以看到这三个方法是addView(),updateViewLayout(),removeView(),即添加、更新、删除。也就是说WindowManager对Window有三种操作。通过这个三种操作,我们来探究下Window的机制。
Window、WindowManager、WMS
在探究Window的增、改、删之前,先来看看Window、WindowManager、WMS三者的之间的关系。我们知道WMS是一个系统服务,它主要是关系窗口的。在这三者之间WindowMnager与WMS通过Binder进行通信,其中Window的具体操作由WMS承担。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JZtXBRcD-1605344544409)(E:\Blog\Image\window-windownager-WMS.png)]
Window的机制
添加一个Window
WIndowManager接口的实现类是WindowManagerImpl,我们直接分析WindowManagerImpl。
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
@Override
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.updateViewLayout(view, params);
}
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
可以看到WindowManagerImpl实现Window的增、删、改是由一个mGlobal的成员实现的。这个mGlobal是WindowManagerGlobal。继续分析WindowManagerClobal。
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
// 1.检查参数
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
if (display == null) {
throw new IllegalArgumentException("display must not be null");
}
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
}
// ...
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// ...
// 2.创建ViewRootImpl
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams<