Android的Window和WindowManager
来源:互联网 发布:传真服务器软件 编辑:程序博客网 时间:2024/06/06 20:01
Window和Windowmanager
window是Android视图View显示的容器,activity、Dialog、Toast中的View都是通过window来呈现的,它是一个抽象类,只有一个实现类phonewindow。windowmanager是访问window的唯一入口,window内添加、删除、更新View的操作都由windowmanager来管理,WindowManager的功能是通过WindowManagerService这个系统服务提供的,两者相互调用是一个IPC的过程。
Window
window其实是一个抽象的概念,并没有在屏幕上有具体的存在,只是作为View的容器有window的属性。添加一个window其实是通过windowManager的addView()来实现的,该方法可以将View以window的形式显示出来。
Windowmanager.LayoutParams 有两个重要的属性flags和type。
flag 表示window的属性,可以控制window的显示特性,有很多,参考开发文档。
比如FLAG_SHOW_WHEN_LOCKED可以将window显示在锁屏界面上。
Type 参数表示window的类型,三类:应用Window,子Window,系统Window。window的类型影响window的显示层级。
应用window对应着activity层级1-99,子window常见的有dialog层级1000-1999,子Window必须附属在特定的父Window上,系统Window需要声明权限才能创建,层级2000-2999,toast,系统状态栏就是系统window。
层级越大就可以在越上层显示。
WindowManager
Windowmanager是用来操作window的类有添加,删除,更新。这些操作实际操作的都是window内部的View
Window的内部机制
Window添加到屏幕
首先从添加Window开始,添加Window其实是addView()即添加View,通过windowmanager的addView()实现,WindowManager的实现类是WindowManagerImp类,而WindowManagerImp的addView()调用了windowManagerGlobal()的addView(),类似ContextWraper调用ContextImp类的方法。可以推测windowmanager的其他两个removeview()和update也是同样的实现方式。
看看WindowManagerGlobal的addView()方法
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } if (display == null) { throw new IllegalArgumentException("display must not be null"); } if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; if (parentWindow != null) { parentWindow.adjustLayoutParamsForSubWindow(wparams); } ViewRootImpl root; View panelParentView = null; 。。。。。。。。。。 root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); if (mViews == null) { index = 1; mViews = new View[1]; mRoots = new ViewRootImpl[1]; mParams = new WindowManager.LayoutParams[1]; } else { index = mViews.length + 1; Object[] old = mViews; mViews = new View[index]; System.arraycopy(old, 0, mViews, 0, index-1); old = mRoots; mRoots = new ViewRootImpl[index]; System.arraycopy(old, 0, mRoots, 0, index-1); old = mParams; mParams = new WindowManager.LayoutParams[index]; System.arraycopy(old, 0, mParams, 0, index-1); } index--; mViews[index] = view; mRoots[index] = root; mParams[index] = wparams; } // do this last because it fires off messages to start doing things try { root.setView(view, wparams, panelParentView); } catch (RuntimeException e) { // BadTokenException or InvalidDisplayException, clean up. synchronized (mLock) { final int index = findViewLocked(view, false); if (index >= 0) { removeViewLocked(index, true); } } throw e; } }
mViews[index] = view; mRoots[index] = root; mParams[index] = wparams;
WindowManagerglobal还将View,viewRoot,params存入了一个数组,所以每个View和ViewRoot是一一对应的,windowmanager进行add,remoteview和update时就可以将相关的参数同时添加和移除。
看到addView是通过ViewRootImp来实现绘制View的,ViewRootImp的setView()方法会绘制View,这在之前的文章中提到过View绘制原理提到的View的绘制是有ViewRoot实现的,ViewRoot的实现类是ViewRootImp。
绘制完View之后通过WindowSession完成添加window到屏幕上,其实现类是Session,是个Binder类型,用于与WindowManagerService进行进程通信。
总结一下:添加的过程.
WindowManager->WindowManagerImp->WindowManagerGlobal.addView()->ViewRootImp.setView()绘制View->Session->WindowManagerService系统进程添加Window
Window删除
直接看Windowmanagerglobal的removeView()
public void removeView(View view, boolean immediate) { if (view == null) { throw new IllegalArgumentException("view must not be null"); } synchronized (mLock) { int index = findViewLocked(view, true); View curView = removeViewLocked(index, immediate); if (curView == view) { return; } throw new IllegalStateException("Calling with view " + view + " but the ViewAncestor is attached to " + curView); } }
private int findViewLocked(View view, boolean required) { if (mViews != null) { final int count = mViews.length; for (int i = 0; i < count; i++) { if (mViews[i] == view) { return i; } } } if (required) { throw new IllegalArgumentException("View not attached to window manager"); } return -1; }
直接找到View的index,这样就可以将数组中的View移除,将被移除的对象会被放入另一个数组中。删除操作是用ViewRootImp的doDie()方法实现的会调用dispatchDetachedFromWindow()方法,该方法通过Session与WindowmanagerService通信,然后调用View的onDetachedFromWindow(),我们在自定义View时,可以在这个方法中我们进行结束动画,停止线程等操作。
更新Window
大致流程和上面类似,更新会重置View的Layoutparams。最终还是由WMS来实现的。
activity的Window的创建过程
首先在启动activity时,会创建activity的window对象,并设置其回调接口,activity实现了window的回调接口callback,所以activity可以处理window相关的事件,比如dispatchTouchEvent()方法。
activity的View是怎么添加到window上的呢?
从activity的setcontentview开始,
public void setContentView(@LayoutRes int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); }
调用了Window的setContentView(),window的实现类是PhoneWindow,
@Override public void setContentView(int layoutResID) { // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window // decor, when theme attributes and the like are crystalized. Do not check the feature // before this happens. if (mContentParent == null) { installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, getContext()); transitionTo(newScene); } else { mLayoutInflater.inflate(layoutResID, mContentParent); } mContentParent.requestApplyInsets(); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } }
首先生成DecorView,将Content添加到DecorView上,执行5.0以上的新增的过渡动画,将布局文件添加到Content中,最后回调window的callback的方法,oncontentchanged(),表示activity的内容已改变。
目前为止还没有将DecorView添加到window中,这步是在Activitythread的HandleResumeActivity()中执行的,回调activity的onResume()并调用windowmanager的addView()将DecorView添加到window中。
activity的window创建完成了布局文件也添加到了Window中。
Toast、Diaolog、PopupWindow、菜单、及状态栏都是通过window实现的。
- Android的Window和WindowManager
- Android的Window和WindowManager
- Android的Window和WindowManager
- Android Window 和 WindowManager
- Android 理解Window 和 WindowManager
- 【Android学习】Window和WindowManager
- android开发window和windowmanager
- Window和WindowManager的分析
- Window和WindowManager的理解
- Android界面生成流程:WindowManager和Window的关系
- Android窗口Window和WindowManager详解
- 【Android API】理解Window和WindowManager
- WindowManager和Window添加View的区别
- 对Window和WindowManager的理解
- Window和WindowManager的工作原理
- Window 和 Windowmanager
- Window和WindowManager解析
- Window和WindowManager小结
- java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
- 极角排序合集
- 简单dp算法——百炼05:切割回文
- 类之间的关系
- mysql使用(2)
- Android的Window和WindowManager
- Linux数据流重定向
- 数据结构实验之链表一:顺序建立链表
- ofbiz连接mysql并创建独立数据库
- JS最佳实践
- Android Studio报错:libpng warning: iCCP: Not recognizing known sRGB profile that has been edited
- linux入门基础命令
- Network Saboteur
- 怎么看时序图--nand flash的读操作详解