Window和WindowManager
Window表示一个窗口的概念,在日常开发中直接接触Window的机会并不多,但是在某些特殊时候我们需要在桌面上显示一个类似悬浮窗的东西,那么这种效果就需要用到Window来实现。Window是一个抽象类,它的具体实现是PhoneWindow。创建一个Window是很简单的事,只需要通过WindowManager即可完成。WindowManager是外界访问Window的入口,Window的具体实现位于WindowManagerService中,WindowManager和WindowManagerService的交互是一个IPC过程。Android中所有的视图都是通过Window来呈现的,不管是Activity、Dialog还是Toast,它们的视图实际上都是附加在Window上的,因此Window实际上是View的直接管理者。
/framework/base/core/java/android/view/Window.java
/framework/base/core/java/android/view/WindowManager.java
/framework/base/core/java/com/android/internal/policy/PhoneWindow.java
/framework/base/core/java/com/android/internal/policy/DecorView.java
/framework/base/services/core/java/com/android/server/wm/WindowManagerService.java
1 . Window:是一个抽象类,它会被作为一个顶级视图添加到WindowManager中,对View进行管理;
public abstract class Window {
//---;
public interface Callback {
//---;
}
//---;
}
2 . PhoneWindow:是Window的唯一实现类,会被添加到WindowManager的根容器;
public class PhoneWindow extends Window implements MenuBuilder.Callback {
//---;
}
3 .
4 .
涉及到的几个类的关系
Window和WindowManager
Window有三种类型,分别是应用Window、子Window和系统Window。应用类Window对应着一个Activity。子Window不能单独存在,需要附属在特定的父Window之中,比如常见的一些Dialog就是一个子Window。系统Window是需要声明权限才能创建Window,比如Toast和系统状态栏这些都是系统Window。
Window是分层的,每个Window都有对应的z-ordered,层级大的会覆盖层极小的Window的上面。在三类Window中,应用Window的层级范围是1~99(其实也就只定义了几个值),子Window的层级范围是100~1999(其实也就只定义了几个值),系统Window的层级范围是2000~2999(其实也就只定义了几十个值),这些层级范围对应着WindowManager.LayoutParams的type参数。如果想要Window位于所有Window的最顶层,那么采用较大的层级即可。很显然,系统Window的层级是最大的,而且系统层级有很多值,一般我们可以选用TYPE_SYSTEM_OVERLAY或者TYPE_SYSTEM_ERROR。系统Window层级需要需要声明权限,比如
WindowManager所提供的功能很简单,常用的只有三个方法,既添加View、更新View、删除View,这三个方法定义在ViewManager中,而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);
}
public interface WindowManager extends ViewManager {
...
}
对于开发者来说,WindowManager常用的就只有这三个功能,但是已经足够我们使用了。它可以创建一个Window并向其添加View,还可以更新Window中的View,另外如果想要删除一个Window,那么只需要删除它里面的View即可。由此来看,WindowManager操作Window的过程更像是在操作Window中的View。
Window的内部机制
Window是一个抽象的概念,每一个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,因此Window并不是实际存在的,它是以View的形式存在。这点可以从WindowManager的定义看出来,它提供的三个接口方法addView、updateViewLayout、removeView都是针对View的,这说明View才是Window存在的实体。在实际使用中无法直接访问Window,对Window的访问必须通过WindowManager。
Window的添加过程
Window的添加过程需要通过WindowManager的addView来实现,WindowManager是一个接口,它的真正实现是WindowManagerImpl类。在WindowManagerImpl中Window的三大操作实现如下:
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
@Override
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.updateViewLayout(view, params);
}
@Override
public void removeView(View view) {
mGlobal.removeView(view, false);
}
}
WindowManagerImpl并没有直接实现Window的三大操作,而是全部交给了WindowManagerGlobal来处理。WindowManagerGlobal以工厂的形式向外提供自己的实例,代码是:private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance()。WindowManagerImpl这种工作模式是典型的桥接模式,将所有的操作全部委托给WindowManagerGlobal来实现。WindowManagerGlobal的addView方法主要分为如下几步:
- 检查参数是否合法,如果是子Window,那么还需要调整一些布局参数;
- 创建ViewRootImpl并将View添加到列表中;
在WindowManagerGlobal内部有如下几个列表比较重要:
//存储所有Window所对应的View;
private final ArrayList<View> mViews = new ArrayList<View>();
//存储所有Window所对应的ViewRootImpl;
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
//存储所有Window所对应的布局参数;
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
//存储那些正被删除的View对象或者那些已经调用removeView方法但是删除操作还未完成的Window对象;
private final ArraySet<View> mDyingViews = new ArraySet<View>();
- 通过ViewRootImpl来更新界面并完成Window的添加过程;
这个步骤由ViewRootImpl的setView方法来完成,在setView方法内部会通过requestLayout方法来完成异步刷新请求。接着会通过WindowSession最终来完成Window的添加过程。WindowSession的类型是IWindowSession,它是一个Binder对象,真正的实现类是Session,也就是Window的添加过程是一次IPC调用。在Session内部会通过WindowManagerService来实现Window的添加。
Window的删除过程
Window的删除过程和添加过程一样,都是先通过WindowManagerImpl后,再进一步通过WindowManagerGlobal来实现的。
Window的更新过程
Window的更新方法是updateViewLayout,首先需要更新View的LayoutParams并替换掉老的LayoutParams,接着再更新ViewRootImpl中的LayoutParams,这一步是通过ViewRootImpl的setLayoutParams方法来实现的。在ViewRootImpl中会通过scheduleTraversals方法来对View重新布局,包括测量、布局、重绘这三个过程。除了View本身的重绘以外,ViewRootImpl还会通过WindowSession来更新Window的视图,这个过程最终是由WindowManagerService的relayoutWindow方法来具体实现的,它同样是一个IPC过程。
Window的创建过程
View是Android中的视图的呈现方式,但是View不能单独存在,它必须附着在Window这个抽象的概念上面,因此有视图的地方就有Window。Android中可以提供视图的地方有Activity、Dialog、Toast之外,还有一些依托于Window而实现的视图,比如PopUpWindow、菜单,它们也是视图。
Activity的Window创建过程
Dialog的Window创建过程
Toast的Window创建过程
-
-
-
-
-
-
-
-
-
-
-
-
-
---------------last line for now-------------------