View,ViewRootImpl和WindowManagerService之间的关系
创始人
2024-05-24 14:21:49
0

1. View,ViewRoot和WindowManager简单介绍

1.1 View和ViewGroup

Android的基本布局控件,结构是树装,ViewGroup实现了ViewParent接口,每个View内部保留一个ViewParent变量,代表他的父节点

1.2 ViewRootImpl

ViewRoot概念的具体实现类,也实现了ViewParent接口,每个View树顶级ViewParent就是这个类,主要管理

  1. View树的measure,layout,draw
  2. 向WindowManagerService注册Window
  3. 接收WindowManagerService的事件回调

1.3 WindowManager

具体实现类WindowManagerImpl,不过最终任务委托给了WindowManagerGlobal对象,负责建立WindowManagerService连接和通信

ViewRootImpl的功能相当于中介,左手掌握的顶级View,右手掌握WindowManger通信

2. ViewRootImpl的起源

2.1 ViewRootImpl创建时机

这个和WindowManager是有点关联的,起点一般是Activity调用resume的时机,这个具体是在ActivityThread类中的


public final class ActivityThread {final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {if (r.window == null && !a.mFinished && willBeVisible) {r.window = r.activity.getWindow();View decor = r.window.getDecorView();decor.setVisibility(4);wm = a.getWindowManager();LayoutParams l = r.window.getAttributes();a.mDecor = decor;l.type = 1;l.softInputMode |= forwardBit;if (r.mPreserveWindow) {a.mWindowAdded = true;r.mPreserveWindow = false;ViewRootImpl impl = decor.getViewRootImpl();if (impl != null) {impl.notifyChildRebuilt();}}if (a.mVisibleFromClient) {if (!a.mWindowAdded) {a.mWindowAdded = true;// 核心wm.addView(decor, l);} else {a.onWindowAttributesChanged(l);}}} else if (!willBeVisible) {r.hideForNow = true;}}
}

wm.addView()函数是入口,wm实际是WindowManager对象,WindowManager真正做工作的类是WindowManagerGlobal

addView()实际上是添加的DecorView ,从r.window获取(Activity的话window实现类是PhoneWindow)

public final class WindowManagerGlobal {public void addView(View view, android.view.ViewGroup.LayoutParams params, Display display, Window parentWindow) {// 省略非必要代码ViewRootImpl root = new ViewRootImpl(view.getContext(), display);view.setLayoutParams(wparams);this.mViews.add(view);this.mRoots.add(root);this.mParams.add(wparams);try {root.setView(view, wparams, panelParentView);} catch (RuntimeException var13) {if (index >= 0) {this.removeViewLocked(index, true);}throw var13;}}}}
}

这时候创建了ViewRootImpl对象,并把View,ViewRootImpl和windowManagerParam保存到WindowManagerGlobal的集合中,root.setView() 负责接力下一棒

2.2 ViewRootImpl通知注册Window

public final class ViewRootImpl implements ViewParent, Callbacks, DrawCallbacks {
public void setView(View view, LayoutParams attrs, View panelParentView) {synchronized(this) {if (this.mView == null) {this.mView = view;// 省略代码try {this.mOrigWindowType = this.mWindowAttributes.type;this.mAttachInfo.mRecomputeGlobalAttributes = true;this.collectViewAttributes();/*** 核心*/res = this.mWindowSession.addToDisplay(this.mWindow, this.mSeq, this.mWindowAttributes, this.getHostVisibility(), this.mDisplay.getDisplayId(), this.mAttachInfo.mContentInsets, this.mAttachInfo.mStableInsets, this.mAttachInfo.mOutsets, this.mInputChannel);} catch (RemoteException var19) {this.mAdded = false;this.mView = null;this.mAttachInfo.mRootView = null;this.mInputChannel = null;this.mFallbackEventHandler.setView((View)null);this.unscheduleTraversals();this.setAccessibilityFocus((View)null, (AccessibilityNodeInfo)null);throw new RuntimeException("Adding window failed", var19);} finally {if (restore) {attrs.restore();}}}}
}
}

ViewRootImpl保存和View对象,这里我们也可以发现 每一个顶级View都会对应一个ViewRootImpl对象,this.mWindowSession.addToDisplay() 通过WindowSession通知WindowManagerService注册Window

3.ViewRootImpl与WindowManagerService的通信

3.1 WindowSession

ViewRootImpl向WindowManagerService发送信息的类,实际上是一个AIDL接口

public interface IWindowSession extends IInterface {}

ViewRootImpl通过WindowManagerGlobal.getWindowSession() 获取WindowSession对象

public static IWindowSession getWindowSession() {synchronized (WindowManagerGlobal.class) {if (sWindowSession == null) {try {// Emulate the legacy behavior.  The global instance of InputMethodManager// was instantiated here.// TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsageInputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary();IWindowManager windowManager = getWindowManagerService();sWindowSession = windowManager.openSession(new IWindowSessionCallback.Stub() {@Overridepublic void onAnimatorScaleChanged(float scale) {ValueAnimator.setDurationScale(scale);}});} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}return sWindowSession;}}

前面注册Window的时候就用到的的就是WindowSession对象的addToDisplay

3.2 IWindow

这个也是一个AIDL接口文件,主要是用于WindowManagerService向ViewRootImpl发送消息,ViewRootImpl调用mWindowSession.addToDisplay注册窗口,会把IWindow这个信使带给WindowManagerService

public final class ViewRootImpl implements ViewParent, Callbacks, DrawCallbacks {static class W extends android.view.IWindow.Stub {private final WeakReference mViewAncestor;private final IWindowSession mWindowSession;W(ViewRootImpl viewAncestor) {this.mViewAncestor = new WeakReference(viewAncestor);this.mWindowSession = viewAncestor.mWindowSession;}public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeNavBar, int displayId) {// 省略实现}public void moved(int newX, int newY) {// 省略实现}public void dispatchAppVisibility(boolean visible) {// 省略实现}public void dispatchGetNewSurface() {// 省略实现}public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {// 省略实现}private static int checkCallingPermission(String permission) {// 省略实现}public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {// 省略实现}public void closeSystemDialogs(String reason) {// 省略实现}public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync) {// 省略实现}public void dispatchWallpaperCommand(String action, int x, int y, int z, Bundle extras, boolean sync) {// 省略实现}public void dispatchDragEvent(DragEvent event) {// 省略实现}public void updatePointerIcon(float x, float y) {// 省略实现}public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility, int localValue, int localChanges) {// 省略实现}public void dispatchWindowShown() {// 省略实现}public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {// 省略实现}public void dispatchPointerCaptureChanged(boolean hasCapture) {// 省略实现}}
}

我们比较熟悉的可能就是WindowFocusChanged这个函数

4. ViewRootImpl与View

这两个关系紧密,我们最容易接触到的是ViewRootImpl控制者View的刷新

void scheduleTraversals() {if (!this.mTraversalScheduled) {this.mTraversalScheduled = true;this.mTraversalBarrier = this.mHandler.getLooper().getQueue().postSyncBarrier();this.mChoreographer.postCallback(2, this.mTraversalRunnable, (Object)null);if (!this.mUnbufferedInputDispatch) {this.scheduleConsumeBatchedInput();}this.notifyRendererOfFramePending();this.pokeDrawLockIfNeeded();}}

scheduleTraversals是刷新方法的起点:

  1. 主线程Handler设置同步屏障(postSyncBarrier),让刷新任务先执行
  2. 注册mChoreographer.postCallback()接收界面更新的同步消息

接收到刷新的同步消息后,执行mTraversalRunnable的run方法,调用ViewRootImpl.doTraversal()

void doTraversal() {if (this.mTraversalScheduled) {this.mTraversalScheduled = false;this.mHandler.getLooper().getQueue().removeSyncBarrier(this.mTraversalBarrier);if (this.mProfile) {Debug.startMethodTracing("ViewAncestor");}this.performTraversals();if (this.mProfile) {Debug.stopMethodTracing();this.mProfile = false;}}}

this.performTraversals()内部调用performMeasure, performLayout, performDraw View树的measure,layout和draw实现刷新

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...