frameworks/base/core/java/android/view/ViewRootImpl.java
final IWindowSession mWindowSession;
final W mWindow;
/**
* The top of a view hierarchy, implementing the needed protocol between View
* and the WindowManager. This is for the most part an internal implementation
* detail of {@link WindowManagerGlobal}.
*
* {@hide}
*/
@SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
...
public ViewRootImpl(Context context, Display display) {
...
mWindowSession = WindowManagerGlobal.getWindowSession();
...
mWindow = new W(this);
...
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this,
context);
...
mChoreographer = Choreographer.getInstance();
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
...
}
...
}
session
在Binder
系统中比较常见,表示客户端与服务端的一次会话。
WindowManagerGlobal.java
/**
* Provides low-level communication with the system window manager for
* operations that are not associated with any particular context.
*
* This class is only used internally to implement global functions where
* the caller already knows the display and relevant compatibility information
* for the operation. For most purposes, you should use {@link WindowManager} instead
* since it is bound to a context.
*
* @see WindowManagerImpl
* @hide
*/
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
//获取InputMethodManager单例对象
InputMethodManager imm = InputMethodManager.getInstance();
//获取WindowManagerService的代理对象
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext())
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
static class W extends IWindow.Stub {
private final WeakReference<ViewRootImpl> mViewAncestor;
private final IWindowSession mWindowSession;
/*ViewRootImpl内部有一个W类型的对象,它也是基于binder通信,
但是它是客户端,处理WindowManagerService的请求。
例如按键,触屏事件的通知:
WindowManagerService接收到事件,WindowManagerService找到
UI位于顶层的进程所对应的IWindow对象,
这是一个Bp端,调用这个IWindow对象的dispatchxxx(),
ViewRootImpl的Bn端IWindow接受事件,再派发给相应的处理者。*/
...
...
...
...
}
ViewRootImpl调用performTraversals方法开始遍历整个View树,执行View的measure,layout,draw流程。View的工作流程就是从performTraversals开始的。其中最核心的就是performTraversals再来看一下其运行调用流程。scheduleTraversals方法调用地方比较多包含了主要包含了如下:
void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView)
void handleAppVisibility(boolean visible)
void handleGetNewSurface()
public void requestFitSystemWindows()
//接Activity.attch之后流程之后在WindowManagerGlobal的addView中会实例化,
//ViewRootImpl并且执行setView将定义的view设置到里面
//而ViewRootImpl.setView中有执行requestLayout一次
public void requestLayout()
void invalidate()
private void invalidateRectOnScreen(Rect dirty)
void setWindowStopped(boolean stopped)
private void profileRendering(boolean enabled)
private void draw(boolean fullRedrawNeeded)
public void requestChildFocus(View child, View focused)
public void clearChildFocus(View child)
public void recomputeViewAttributes(View child)
public void handleDispatchSystemUiVisibilityChanged(SystemUiVisibilityInfo args)
scheduleTraversals中通过mChoreographer.postCallback一个mTraversalRunnable线程
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
if (ViewDebugManager.DEBUG_SCHEDULETRAVERSALS) {
Log.v(mTag, "scheduleTraversals: mTraversalBarrier = " + mTraversalBarrier
+ ",this = " + this, new Throwable("scheduleTraversals"));
}
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
....
....
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
其中就是运行到performTraversals()代码量比较大,但是核心是三个方法
1.performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
2.performLayout(lp, mWidth, mHeight);
3.performDraw();
...
...
if (!mStopped || mReportNextDraw) {
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
(relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0);
if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
|| mHeight != host.getMeasuredHeight() || contentInsetsChanged ||
updatedConfiguration) {
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
...
// Ask host how big it wants to be
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
...
...
if (didLayout) {
...
performLayout(lp, mWidth, mHeight);
...
}
...
...
boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
...
if (!cancelDraw && !newSurface) {
if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
for (int i = 0; i < mPendingTransitions.size(); ++i) {
mPendingTransitions.get(i).startChangingAnimations();
}
mPendingTransitions.clear();
}
performDraw();
}else{
if (isViewVisible) {
// Try again
scheduleTraversals();
} else if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
for (int i = 0; i < mPendingTransitions.size(); ++i) {
mPendingTransitions.get(i).endChangingAnimations();
}
mPendingTransitions.clear();
}
}
Activity调用setContentView会调用PhoneWindow的setContentView,最后会调用DecorView的addView方法,这也说明了我们添加的View是DecorView的子元素。
ViewRootImpl中的调用流程基本调用流程:
requestLayout
-->
scheduleTraversals()
-- >
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null)
-->
doTraversal()
-->
performTraversals()