每个Activity都有一个Window对象,这个对象是PhoneWindow类型的。
每个Window对象里面都维护着一个WindowManager对象。
Activity里面添加一个View是通过WindowManager的addView()方法实现的
相关关键类WindowManagerService
高层级,系统窗口管理服务
Window
一个顶级窗口的外观和行为策略的一个抽象基类。
Window并不是真实存在的,它表示一种抽象的功能集合,View才是Android中的视图呈现形式,绘制到屏幕上的是View不是Window,但是View不能单独存在,它必需依附在Window这个抽象的概念上面,Android中需要依赖Window提供视图的有Activity,Dialog,Toast,PopupWindow,StatusBarWindow(系统状态栏),输入法窗口等,因此Activity,Dialog等都维护着一个Window对象。当我们调用Activity的setContentView()时,其实最终会调用Window的setContentView(),当我们调用Activity的findViewById()时,其实最终调用的是Window的findViewById()。
对 Window 的操作是通过 WindowManager 来完成的。
WindowManager
WindowManager是一个接口,里面常用的方法有:添加View,更新View和删除View,WindowManager继承自ViewManager,这三个方法定义在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);
}
WindowManagerImpl
低层次,负责与系统窗口管理服务进行操作通信,与Context进行关联。
是WindowManager的实现类,大部分工作都通过WindowManagerGlobal来实现。
WindowManagerGlobal
低层次,负责与系统窗口管理服务进行操作通信,不与Context进行关联。
ViewRootImpl
ViewRootImpl是一个视图层次结构的顶部,它实现了View与WindowManager之间所需要的协议,作为WindowManagerGlobal中大部分的内部实现,也就说WindowManagerGlobal方法最后还是大部分调用了ViewRootImpl。
类似 ApplicationThread 负责跟AMS通信一样,ViewRootImpl 的一个重要职责就是跟 WMS 通信,它通过静态变量 sWindowSession(IWindowSession实例,在WindowManagerGlobal中创建)与 WMS 进行通信。
ActivityThread.handleResumeActivity()方法 :
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason) {
...//其他代码
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
...//其他代码
}
调用WindowManagerImpl.addView() :
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
调用WindowManagerGlobal.addView():
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
...//其他代码
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(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.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
调用ViewRootImpl.java的setView方法
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
...//其他代码
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout(); //请求布局
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
mInputChannel = new InputChannel();
}
mForceDecorViewVisibility = (mWindowAttributes.privateFlags
& PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY) != 0;
try {
mOrigWindowType = mWindowAttributes.type;
mAttachInfo.mRecomputeGlobalAttributes = true;
collectViewAttributes();
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
}
...//其他代码
}
res = mWindowSession.addToDisplay() 调用了Session的addToDisplay()方法:
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
Rect outStableInsets, Rect outOutsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
}
调用mService.addWindow()方法添加Window,这个mService其实就是WindowManagerService对象,也就是说布局最终是由 WindowManagerService 来添加的。
分析到这里可以看到,ViewRootImpl是通过 mWindowSession(来自WindowManagerGlobal的sWindowSession对象)和WindowManagerService通信的。
参考:
ViewManager、ViewRootImp、WindowManagerImpl、WindowSession等详细解析
Android窗口机制(一)——Window,PhoneWindow,DecorView理解
Window窗口机制(二)——Window,WindowManager理解
Window窗口机制(三)——WindowManager,ViewRootImpl,View理解
Android 窗口机制
Android窗口机制(四)ViewRootImpl与View和WindowManager
android WindowManagerService
Window, WindowManager和WindowManagerService之间的关系
android window(三)ViewRootImpl
ViewRootImpl的独白,我不是一个View(布局篇)
ViewRootImpl源码分析事件分发
面试进阶之窗口机制
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/Window.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/WindowManagerImpl.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/WindowManagerGlobal.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/view/ViewRootImpl.java
http://androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/services/core/java/com/android/server/wm/Session.java
https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
作者:yzpyzp