美文网首页面试
WindowManagerService

WindowManagerService

作者: 吕志豪 | 来源:发表于2018-03-03 17:43 被阅读6次
Window 层级
应用 Window 1~99
子 Window 1000~1999
系统 Window 2000~2999

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

image.png
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,应该添加权限:

    <uses-permission android:name="android.permission.SYSTEM_ALERT_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);
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

    本文链接:https://www.haomeiwen.com/subject/zgatfftx.html