1.什么是Window
1.1、代码层面来看,Window是一个abstract类。
12345678910111213/*** Abstract base class for a top-level window look and behavior policy. An* instance of this class should be used as the top-level view added to the* window manager. It provides standard UI policies such as a background, title* area, default key processing, etc.** <p>The only existing implementation of this abstract class is* android.view.PhoneWindow, which you should instantiate when needing a* Window.*/public abstract class Window {...}1.2、解释
- Window是为顶级View提供的一个抽象类,该实现类应该作为顶级的view被添加到WindowManager中
- WindowManager提供了标准的ui规则,比如:背景,标题等
- 仅仅有一个存在的实例PhoneWindow,当需要Window时,实例PhoneWindow即可。
2.什么是WindowManager
- 2.1、直接看WindowManager interface的实现类
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798/*** Provides low-level communication with the system window manager for* operations that are bound to a particular context, display or parent window.* Instances of this object are sensitive to the compatibility info associated* with the running application.** This object implements the {@link ViewManager} interface,* allowing you to add any View subclass as a top-level window on the screen.* Additional window manager specific layout parameters are defined for* control over how windows are displayed. It also implements the {@link WindowManager}* interface, allowing you to control the displays attached to the device.** <p>Applications will not normally use WindowManager directly, instead relying* on the higher-level facilities in {@link android.app.Activity} and* {@link android.app.Dialog}.** <p>Even for low-level window manager access, it is almost never correct to use* this class. For example, {@link android.app.Activity#getWindowManager}* provides a window manager for adding windows that are associated with that* activity -- the window manager will not normally allow you to add arbitrary* windows that are not associated with an activity.*/public final class WindowManagerImpl implements WindowManager {private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();private final Display mDisplay;private final Window mParentWindow;private IBinder mDefaultToken;public WindowManagerImpl(Display display) {this(display, null);}private WindowManagerImpl(Display display, Window parentWindow) {mDisplay = display;mParentWindow = parentWindow;}public WindowManagerImpl createLocalWindowManager(Window parentWindow) {return new WindowManagerImpl(mDisplay, parentWindow);}public WindowManagerImpl createPresentationWindowManager(Display display) {return new WindowManagerImpl(display, mParentWindow);}/*** Sets the window token to assign when none is specified by the client or* available from the parent window.** @param token The default token to assign.*/public void setDefaultToken(IBinder token) {mDefaultToken = token;}@Overridepublic void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {applyDefaultToken(params);mGlobal.addView(view, params, mDisplay, mParentWindow);}@Overridepublic void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {applyDefaultToken(params);mGlobal.updateViewLayout(view, params);}private void applyDefaultToken(@NonNull ViewGroup.LayoutParams params) {// Only use the default token if we don't have a parent window.if (mDefaultToken != null && mParentWindow == null) {if (!(params instanceof WindowManager.LayoutParams)) {throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");}// Only use the default token if we don't already have a token.final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;if (wparams.token == null) {wparams.token = mDefaultToken;}}}@Overridepublic void removeView(View view) {mGlobal.removeView(view, false);}@Overridepublic void removeViewImmediate(View view) {mGlobal.removeView(view, true);}@Overridepublic Display getDefaultDisplay() {return mDisplay;}}2.2、解释
- WindowManager 是用来提供低等级的通讯跟system window manager 。例如:绑定context/显示/父Window的操作
- 允许添加任何的View作为高等级的Window。
- 一般我们不会直接用WindowManager,通常在Activity、Dialog上使用
2.3、功能
- addView() 添加View
- updateViewLayout() 刷新布局
- applyDefaultToken()
- removeView()
- 以上所有操作均是通过单例类 WindowManagerGlobal 完成
3.什么是WindowManagerGlobal
- 3.1、WindowManagerGlobal是App中全局的窗口管理模块
- 3.2、WindowManagerGlobal 主要用来与WMS进行交互。
- 3.3、那么问题来了怎么跟WMS交互?
- 通过Binder进程间的通信获取WMS的session
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869public static IWindowSession getWindowSession() {synchronized (WindowManagerGlobal.class) {if (sWindowSession == null) {try {InputMethodManager imm = InputMethodManager.getInstance();// a. 获取WMSIWindowManager windowManager = getWindowManagerService();// b.拉取sessionsWindowSession = windowManager.openSession(new IWindowSessionCallback.Stub() {@Overridepublic void onAnimatorScaleChanged(float scale) {ValueAnimator.setDurationScale(scale);}},imm.getClient(), imm.getInputContext());} catch (RemoteException e) {Log.e(TAG, "Failed to open window session", e);}}// c.返回WMS中的sessionreturn sWindowSession;}}public static IWindowManager getWindowManagerService() {synchronized (WindowManagerGlobal.class) {if (sWindowManagerService == null) {// 进程间通信 binder使用sWindowManagerService = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));try {sWindowManagerService = getWindowManagerService();ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());} catch (RemoteException e) {Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e);}}return sWindowManagerService;}}public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow) {...ViewRootImpl root;View panelParentView = null;synchronized (mLock) {// Start watching for system// The previous removeView() had not completed executing. Now it has.// ...// If this is a panel window, then// a.实例该View的ViewRootImplroot = new ViewRootImpl(view.getContext(), display);// b.设置布局位置参数view.setLayoutParams(wparams);// c.存储view,ViewRootImpl,paramsmViews.add(view);mRoots.add(root);mParams.add(wparams);}// do this last because it fires off messages to start doing things// d.将view添加到(显示View)root.setView(view, wparams, panelParentView);}- 3.4、WMS 中的session 存储在了WindowManagerGlobal单例类的实例中,那么如何用到的呢。在addView()中,最后看到 root.setView(view, wparams, panelParentView)了,那么ViewRootImpl到底是什么?
4.什么是ViewRootImpl
|
|
|
|
4.1、ViewRootImpl 中获取WindowManagerGlobal中的session,改session 是通过Binder获取WMS中的,在ViewRootImpl进行线程检测、layout,measure,draw等一系列操作。最终ViewRootImpl通过session去通知WMS显示mWindow。
总结