08 理解Window和WindowManager

2019/03/06 posted in  Android开发艺术探索

8.1 Window和WindowManager

Window表示的是一个窗口的概念,它的具体实现是PhoneWindow,创建一个Window很简单,只需要WindowManager去实现,WindowManager是外界访问Window的入口,Window的具体实现是在WindowManagerService中,他们两个的交互是一个IPC的过程,Android中的所有视图都是通过Window来实现的。

Flag参数

  • FLAG_NOT_FOCUSABLE
    • 表示窗口不需要获取焦点,也不需要接收各种事件,最终的事件会传递给下层的具体焦点的window
  • FLAG_NOT_TOUCH_MODAL
    • 在此模式下,系统会将当前window区域以外的单击事件传递给底层的Window,此前的Window区域以内的单机事件自己处理,
  • FLAG_SHOW_WHEN_LOCKED
    • 开启这个属性可以让window显示在锁屏上

Type参数表示window的类型,window有三种类型,分别是应用,子,系统,应用window对应一个Activity,子Window不能单独存在,需要依赖一个父Window。

Window是分层的,每个Window对应着z-ordered,层级大的会覆盖在层级小的Window上面,这和HTML中的z-index的概念是一致的,在这三类中,应用是层级范围是1-99,子window的层级是1000-1999,系统的层级是2000-2999。这些范围对应着type参数,如果想要window在最顶层,那么层级范围设置大一点就好了,很显然系统的值要大一些,系统的值很多,我们一般会选择TYPE_SYSTEM_OVERLAY和TYPE_SYSTEM_ERROR,还需要声明权限。

WindowManager所提供的功能很简单,常用的有三个方法,添加View,更新View,删除View,这三个方法定义在ViewManager中,而WindowManager继承自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);
    }

我们常见的可以拖动的View,其实也很好实现,就是不断的更改他xy的位置:

    btn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int rawX = (int) event.getRawX();
                int rawY = (int) event.getRawY();
                switch (event.getAction()) {
                    case MotionEvent.ACTION_MOVE:
                        layout.x = rawX;
                        layout.y = rawY;
                        wm.updateViewLayout(btn,layout);
                        break;
                }
                return false;
            }
        });

8.2 Window的内部机制

Window是一个抽象的概念,每一个Window都对应着一个View和一个ViewRootlmpl,Window和View通过ViewRootImpl 来建立联系,因此Window并不是实际存在的,它是以View的形式存在。这点从WindowManager的定义也可以看出,它提供的三个接口方法addView、updateViewLayout以及removeView都是针对View的,这说明View才是Window存在的实体。在实际使用中无法直接访问Window, 对Window 的访问必须通过WindowManager。为了分析Window的内部机制,这里从Window的添加、删除以及更新说起。

8.2.1 Window的添加过程

WindowManagerImpl并没有直接去实现一个Window的三大操作,而是全部交给了WindowManagerGlobal来处理,WindowManagerGlobal是一个工厂的性质提供自己的实现。WindowManagerImpl这种工作模式就是典型的桥接模式,将所有的操作全部委托给WindowManagerGlobal去实现,WindowManagerGlobal的addView方法主要分如下几步:

  1. 检查参数是否合法,如果是子Window还需要调整一下参数
  2. 创建ViewRootImpl并将View添加到列表中
  3. 通过ViewRootImpl来更新界面并完成Window的添加

8.2.2 Window的删除过程

8.2.3 Window的更新过程

8.3 Window的创建过程

8.3.1 Activity的Window创建过程

8.3.2 Dialog的Window创建过程

8.3.3 Toast的Window创建过程