Android的基本布局控件,结构是树装,ViewGroup实现了ViewParent接口,每个View内部保留一个ViewParent变量,代表他的父节点
ViewRoot概念的具体实现类,也实现了ViewParent接口,每个View树顶级ViewParent就是这个类,主要管理
具体实现类WindowManagerImpl,不过最终任务委托给了WindowManagerGlobal对象,负责建立WindowManagerService连接和通信
ViewRootImpl的功能相当于中介,左手掌握的顶级View,右手掌握WindowManger通信
这个和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() 负责接力下一棒
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
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
这个也是一个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这个函数
这两个关系紧密,我们最容易接触到的是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实现刷新