Android布局控件View ViewRootImpl WindowManagerService关系

这篇文章主要为大家介绍了Android布局控件View ViewRootImpl WindowManagerService关系示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

1. View,ViewRoot和WindowManager简单介绍

1.1 View和ViewGroup

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

1.2 ViewRootImpl

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

  • View树的measure,layout,draw
  • 向WindowManagerService注册Window
  • 接收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 @UnsupportedAppUsage InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary(); IWindowManager windowManager = getWindowManagerService(); sWindowSession = windowManager.openSession( new IWindowSessionCallback.Stub() { @Override public 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是刷新方法的起点:

主线程Handler设置同步屏障(postSyncBarrier),让刷新任务先执行

注册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实现刷新

以上就是Android布局控件View ViewRootImpl WindowManagerService关系的详细内容,更多关于Android布局控件的资料请关注0133技术站其它相关文章!

以上就是Android布局控件View ViewRootImpl WindowManagerService关系的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » 移动