美文网首页
Window和WindowManager

Window和WindowManager

作者: 玄策 | 来源:发表于2017-08-27 21:53 被阅读18次

参考资料

凯子哥带你学Framework· Activity界面显示全解析-上
凯子哥带你学Framework Activity界面显示全解析-下
重要:!!! Android 屏幕刷新机制


目录

  • 1)简介
  • 2)Window的内部机制
    • 2.1)Window的添加过程
    • 2.2)Window的删除过程
    • 2.3)Window的更新过程
  • 3)Window的创建过程
    • 3.1)Activity的Window创建过程
    • 3.2)Dialog的Window创建过程
    • 3.3)Toast的Window创建过程

1)简介

  • Window是一个抽象类,具体实现为PhoneWindow
  • 只需要WindowManager即可创建一个Window
  • WindowManager是个接口,是外界访问Window的入口,具体实现位于WindowManagerService(WMS),WindowManager和WindowManagerService的交互是一个IPC过程
  • Android所有视图都是附加在Window上,通过Window来呈现,因此Window是View的直接管理者。如事件分发就是通过Window传递给DecorView。
  • 站在系统角度,Window代表一块显示区域,系统并不关心Window内的绘制内容
//WindowManager可以通过下面两种方式进行获取
WindowManager mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 
WindowManager mWindowManager = (WindowManager) getWindowManger();
//WindowManager添加一个Window
mWindowManager.addView(mButton, mLayoutParams); 

2)Window的内部机制

Window是以View的形式存在,View的绘制流程从ViewRoot开始,ViewRoot对应ViewRootImpl类,它是连接WindowManager和DecorView的纽带。

public interface ViewManager  
{  
    public void addView(View view, ViewGroup.LayoutParams params);  
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);  
    public void removeView(View view);  
}  

->ViewManager.addView
->WindowManager.addView(也是接口,继承ViewManager)
->WindowManagerImpl.addView(实现了WindowManager接口)
->WindowManagerGlobal.addView(接受WindowManagerImpl的委托,并构建ViewRootImpl)
->ViewRootImpl.setView(ViewRooImpl是WindowManagerGlobal的addView方法中新建的对象)
->requestLayout(setView中的一个方法调用,调用performTraversals绘制整个view树)
->WindowSession.addToDisplay(在setView方法中,它是一个Binder对象,用于与WindowManagerService进行IPC通信)
->Session(WindowSession的具体实现)
->WindowManagerService(实现Window的添加)

ViewRootImpl负责管理视图树和与WMS交互,它是WindowManager和DecorView的纽带,与WMS交互是通过WindowSession。而且ViewRootImpl也负责UI界面的布局与渲染,负责把一些事件分发至Activity,以便Activity可以截获事件。大多数情况下,它管理Activity顶层视图DecorView,它相当于MVC模型中的Controller。


3)Window的创建过程

3.1)Activity的Window创建过程

Activity 四大组件之一, 是存放View对象的容器,也是我们界面的载体,可以用来展示一个界面。它有一个SetContentView()方法 ,可以将我们定义的布局设置到界面上
View 就是一个个视图的对象
Window 抽象类,是一个顶层的窗口,它的唯一实例是PhoneWindow它提供标准的用户界面策略,如背景、标题、区域,默认按键处理等

Activity就像是一扇贴着窗花的窗口,Window就想上窗口上面的玻璃,而View对象就像一个个贴在玻璃上的窗花。

  • Activity最终会由ActivityThread中的performLaunchActivity来完成启动,此方法内会通过类加载器创建Activity的实例对象,并调用attach关联所依赖的上下文。
  • 在attach方法中,系统会创建Activity所属的Window对象,并获取了WindowManager对象。
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);/设置回调函数,使得Activity可以处理一些事件,如dispatchTouchEvent()
  • setContentView()调用了Window的setContentView(),将界面绘制交给了Window对象,也就是View通过Activity添加到了Window上面。
    • DecorView是PhoneWindow的内部类,继承自FrameLayout,是最底层的界面
    • 如果没有DecorView,则创建它
    • 将View添加到DecorView的mContentParent对象中
    • 回调Activity的onContentChanged()通知Activity视图已改变
  • 经过上面步骤DecorView已初始化,且Activity的布局也被添加到了DecorView的mContentParent对象中。但这时DecorView还没有被WindowManager添加到Window中,
void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
    }

在Activity的onResume()中,WindowManager会执行addView(mDecorView,getWindow().getAttributes())。至此Activity的视图才能被用户看见。

20151028131646957.png

3.2)Dialog的Window创建过程

AlertDialog和Activity一样,内部有一个Window,我们构造AlertDialog.Builder,通过Builder设置Dialog各种属性,,这些参数会被放在一个名为P(AlertController类型)的变量中,在调用AlertDialog.Builder.create方法的时候,内部首先会new一个 AlertDialog,AlertDialog的父类Dialog的构造函数中会new一个PhoneWindow赋值给AlertDialog中的Window,并且为它设置了回调。AlertDialog创建之后执行apply方法,将P中的参数设置赋值给Dialog,后我们调用Dialog.show方法展示窗口,内部调用dispatchOnCreate,最终会走到setContentView,到此Dialog的Window和Dialog视图关联到了一起,最后执行mWindowManager.addView方法,通过WindowManager将DecorView添加到Window之中,此时Dialog显示在了我们面前。

  • 在Activity中使用Dialog的时候,为什么有时候会报错“Unable to add window -- token is not valid; is your activity running?”?
    答:
    一般发生在Activity进入后台,Dialog没有主动Dismiss掉,然后从后台再次进入App的时候。
    Window分为三种,子窗口,应用窗口和系统窗口,子窗口必须依附于一个上下文,就是Activity,因为它需要Activity的appToken,
    子窗口的window,比如Dialog,想要显示必须保证appToken与Activity保持一致,当Activity销毁,再次回来的时候,Dialog试图重新创建,调用ViewRootImpl的setView()的时候会出问题,所以当Activity不可见的时候,主动Dismiss掉Dialog,否则会因为appToken为空crash。
  • 在子线程中为什么不能显示Toast?
    Toast源码是与NotificationManagerService进行IPC通信,
    show()的时候,通过handler来接收,子线程中没有handler,所以无法显示。可以给子线程添加Looper
sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
  • 为什么不能在setContentView()之后设置某些Window属性标志?
public void setContentView(View view) {
        getWindow().setContentView(view);
        initWindowDecorActionBar();//初始化window属性
}

在Activity.setContentView()之后,Window的一些特征位将被锁定

相关文章

  • Android进阶(8)| Window和WindowManag

    一.Window和WindowManager 1.通过WindowManager添加Window的过程 代码如下:...

  • Window和WindowManager

    1.Window是抽象的概念,每个Window对应一个View和ViewRootImpl,实际上是以View的形式...

  • Window和WindowManager

    参考资料 凯子哥带你学Framework· Activity界面显示全解析-上凯子哥带你学Framework Ac...

  • Window和WindowManager

    参考《Android开发艺术探索》第八章

  • Window 和 WindowManager

    这篇文章是本着抛砖引玉的目的,如果有不严谨,甚至错误地方,劳驾各位指正。 有一群很(hua)好(qian)学(ma...

  • Window和WindowManager

    在WinodwManagerGlobal中,ViewRootImpl(在老版本中为ViewRoot类)起到了绘制V...

  • Window 和 WindowManager

    概述 window window 是一个抽象类,具体实现是PhoneWindow window 也是一个抽象的概念...

  • Window和WindowManager

    在屏幕上创建一个浮动试图 首先实现一个功能,在屏幕上创建一个浮窗,创建一个Window,这一步只需要使用Windo...

  • window和windowManager

    window是一个抽象类,它的具体实现时PhoneWindow,创建window是由windowManager来完...

  • Window和WindowManager

    Window和WindowManager 标签(空格分隔): android 一些简单的定义: WindowMan...

网友评论

      本文标题:Window和WindowManager

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