ViewRootImpl绘制

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);
...
    }
...
}

sessionBinder系统中比较常见,表示客户端与服务端的一次会话。 

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()

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值