深入了解 Window和WindowManager

来源:互联网 发布:房地产市场调研 知乎 编辑:程序博客网 时间:2024/05/20 18:46

深入了解Window和WindowManager

Window是一个抽象的概念,每一个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立连接。在实际使用中无法直接访问Window,对于Window的访问必须通过WindowManager。所有要显示到屏幕上的内容(Activity、dialog、toast、PopupWindow、菜单以及状态栏等)都是通过WindowManager来操作的。

Window的内部机制

Window的增删操作通过WindowManager来完成。
WindowManager的实现类为WindowManagerImpl,其内部真正的处理者为WindowManagerGlobal。

Window的添加

  1. 检查参数是否合法,如果是子Window那么还需要调整一些布局。
  2. 创建ViewRootImpl并将View添加到列表中
    1. mViews存储所有WIndow对应的View
    2. mRoots存储所有Window对应的ViewRootImpl
    3. mParams存储的是所有WIndow所对应的参数布局
    4. mDyingViews存储了那些正在被删除的View对象
  3. 通过ViewRootImpl的setView来更新界面并完成Window的添加过程
  4. 最终通过Session(Binder)来完成Windwo的添加过程(Session内部通过WindowManagerService来实现Window的添加,WMS内部会为每一个应用保留一个单独的Session)

#

public void addView(View view, ViewGroup.LayoutParams params,        Display display, Window parentWindow) {           //2        ViewRootImpl root;            root = new ViewRootImpl(view.getContext(), display);        view.setLayoutParams(wparams);        mViews.add(view);        mRoots.add(root);        mParams.add(wparams);    }    //3    root.setView(view, wparams, panelParentView);     }

删除和更新过程和添加过程一样,都是通过WIndowManagerImpl,在进一步通过WindowManagerGlobal来实现的。

Window的创建过程

Activity的Window创建过程

由ActivityThread的performLaunchActivity()来最终完成启动过程
->
在这之中,会通过类加载器创建Activity的实例对象,并调用attach方法为其关联运行过程中所依赖的一系列上下文环境变量
->
在attach方法中,系统会创建Activity所属的Window对象并为其设置回调接口(Activity实现了Window的Callback接口,如onAttachedToWindow、onDetachedFromWindow、dispatchTouchEvent等)。

调用OnCreate方法 -> setContentView -> PhoneWindow.setCOntentView
->
1. 如果没有DecorView,那么就创建它
2. 将View添加到DecorView的mCOntentParent中
3. 回调Activity的onContentChanged方法通知Activity视图已发生改变

这时,DecorView还没有被WindowManager添加到Window中

在ActivityThread.handleResumeActivity方法中,首先会调用Activity的Resume方法,接着调用Activity的makeVisible()来让DecorView真正添加和显示。

Dialog的Window创建过程

Dialog的Window的创建过程和Activity类似

  1. 创建Window
  2. 初始化DecorView并将Dialog的视图添加到DecorView中
  3. 将DecorView添加到Window中并显示

当Dialog被关闭时,会通过WindowManager来移除DecorView

Toast的Window创建过程

Toast也是基于Window来实现的,但是由于Toast具有定时取消功能,所以系统采用了handler();

管理Toast的类是NotificationManagerService,显示和隐藏Toast都需要通过Toast.TN(Binder)来实现与NMS的跨进程。

当NMS处理Toast的显示或隐藏请求时会跨进程回调TN中的方法,这个时候由于TN运行在Binder线程池中,所以需要通过Handler将其切换到当前线程(发送Toast请求所在的线程)中。
由于这里用到了Handler,所以这意味着Toast无法在没有Looper的线程中弹出。

其他

读书笔记于《Android开发艺术探索》

0 0
原创粉丝点击