本文共 5346 字,大约阅读时间需要 17 分钟。
DecorView通过PhoneWindow与WindowManagerService通信原理图
每个Activity都有一个Window对象,这个对象是PhoneWindow类型的。
每个Window对象里面都维护着一个WindowManager对象。Activity里面添加一个View是通过WindowManager的addView()方法实现的
相关关键类
高层级,系统窗口管理服务 一个顶级窗口的外观和行为策略的一个抽象基类。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是一个接口,里面常用的方法有:添加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);}低层次,负责与系统窗口管理服务进行操作通信,与Context进行关联。 是WindowManager的实现类,大部分工作都通过WindowManagerGlobal来实现。 低层次,负责与系统窗口管理服务进行操作通信,不与Context进行关联。 ViewRootImpl是一个视图层次结构的顶部,它实现了View与WindowManager之间所需要的协议,作为WindowManagerGlobal中大部分的内部实现,也就说WindowManagerGlobal方法最后还是大部分调用了ViewRootImpl。 类似 ApplicationThread 负责跟AMS通信一样,ViewRootImpl 的一个重要职责就是跟 WMS 通信,它通过静态变量 sWindowSession(IWindowSession实例,在中创建)与 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方法
/** * We have one child */ 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() 调用了的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 来添加的。
分析到这里可以看到,ViewRootImpl是通过 mWindowSession(来自的sWindowSession对象)和WindowManagerService通信的。参考:
转载地址:https://blog.csdn.net/yzpbright/article/details/104583793 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!