WindowManagerService

Window 层级
应用 Window 1~99
子 Window 1000~1999
系统 Window 2000~2999

WindowManagerService 添加一个窗口的过程,其实就是 WindowManagerService 为其分配一块 Surface 的过程,一块块的 Surface 在 WindowManagerService 的管理下有序的排列在屏幕上,Android 才得以呈现出多姿多彩的界面。
WindowManagerService 就是位于 Framework 层的窗口管理服务,它的职责就是管理系统中的所有窗口。

WindowManagerService_第1张图片
image.png

WindowManagerService_第2张图片
image.png

Window 有三种类型,分别是应用 Window、子 Window 和系统 Window。应用类 Window 对应一个 Acitivity,子 Window 不能单独存在,需要依附在特定的父 Window 中,比如常见的一些 Dialog 就是一个子 Window。系统 Window是需要声明权限才能创建的 Window,比如 Toast 和系统状态栏都是系统 Window。

Window 层级
应用 Window 1~99
子 Window 1000~1999
系统 Window 2000~2999

WindowManager 使用

我们对 Window 的操作是通过 WindowManager 来完成的,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);
}

这三个方法其实就是 WindowManager 对外提供的主要功能,即添加 View、更新 View 和删除 View。
如果要设置为系统 Window,应该添加权限:

    
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                0, 0,
                PixelFormat.TRANSPARENT
        );
        // flag 设置 Window 属性
        layoutParams.flags= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        // type 设置 Window 类别(层级)
        layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
        layoutParams.gravity = Gravity.CENTER;
        WindowManager windowManager = getWindowManager();
        windowManager.addView(floatingButton, layoutParams);
WindowManagerService_第3张图片
image.png

终于,Window 的添加请求移交给 WindowManagerService 手上了,在 WindowManagerService 内部会为每一个应用保留一个单独的 Session,具体 Window 在 WindowManagerService 内部是怎么添加的,就不对其进一步的分析.
与WMS建立Session之后就调用ViewRootImpl的setView方法,
setView很复杂,我们关注两步:

  • requestLayout
  • 向WMS发起显示当前Window的请求
    @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();//发送DO_TRAVERSAL消息
        }
    }

就是往Handler中发送一个DO_TRAVERSAL消息,这个消息会触发整个视图树的绘制操作,最终会执行performTraversals函数,在performDraw中,framework会获取到图形绘制表面Surface对象,通过mSurface.lockCanvas获取canvas.
视图树绘制流程:

  • 判断是CUP还是GPU绘制.
  • 获取绘制表面Surface对象.
  • 通过Surface对象获取并锁住Canvas绘图对象.
  • 从DecorView开始发起整颗视图树的绘制流程.
  • Surface对象解锁Canvas,并且通知SurfaceFlinger更新视图.

Window 的创建过程

View 是 Android 中的视图的呈现方式,但是 View 不能单独存在,它必须附着在 Window 这个抽象的概念上面,因此有视图的地方就有 Window.
Activity、Dialog、Toast 等视图都对应着一个 Window.
Activity 的 Window 创建就发生在 attach 方法里

mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
...
public Window  makeNewWindow(Context context){
   return new PhoneWindow(context);
}

Window 的具体实现类的确是 PhoneWindow。到这里 Window 以及创建完成了.
Activity 的视图是怎么附属到 Window 上的?从 setContentView 入手.
PhoneWindow 的相关逻辑即可,它的处理步骤如下:

  • 如果没有 DecorView 就创建一个

DecorView 是 Activity 中的顶级 View,是一个 *FrameLayout,一般来说它的内部包含标题栏和内容栏,但是这个会随着主题的变化而改变,不管怎么样,内容栏是一定存在的,并且有固定的 id:”android.R.id.content”,在 PhoneWindow 中,通过 generateDecor 方法创建 DecorView,通过 generateLayout 初始化主题有关布局。

  • 将 View 添加到 DecorView 的 mContentParent 中

这一步较为简单,直接将 Activity 的视图添加到 DecorView 的 mContentParent 中即可,由此可以理解 Activity 的 setContentView 这个方法的来历了,为什么不叫 setView 呢?因为 Activity 的布局文件只是被添加到 DecorView 的 mContentParent 中,因此叫 setContentView 更加具体准确。

  • 回调 Activity 的 onContentChanged 方法通知 Activity 视图已经发生改变

前面分析到 Activity 实现了 Window 的 Callback 接口,这里当 Activity 的视图已经被添加到 DecorView 的 mContentParent 中了,需要通知 Activity,使其方便做相关的处理。
DecorView 已经被创建并初始化完毕,Activity 的布局文件也已经成功添加到了 DecorView 的 mContentParent 中,但是这个时候 DecorView 还没有被 WindowManager 正式添加到 Window 中
在Acitivy 的 onResume 方法中,接着会调用 Acitivy 的 makeVisible() 方法,正是在 makeVisible 方法中,DecorView 才真正的完成了显示过程,到这里 Activity 的视图才能被用户看到,如下:

void makeVisible(){
   if(!mWindowAdded){
      ViewManager wm = getWindowManager();
      wm.addView(mDecor, getWindow().getAttributes());
      mWindowAdded = true;
   }
   mDecor.setVisibility(View.VISIBLE);
}

任何 View 都是附属在一个 Window 上面的,Window 表示一个窗口的概念,也是一个抽象的概念,Window 并不是实际存在的,它是以 View 的形式存在的。WindowManager 是外界也就是我们访问 Window 的入口,Window 的具体实现位于 WindowManagerService 中,WindowManagerService 和 WindowManager 的交互是一个 IPC 过程。

你可能感兴趣的:(WindowManagerService)