ViewRootImpl.setView之后的relayout流程

对接https://blog.csdn.net/chi_wy/article/details/89187791中的部分继续跟一下代码

wm是ViewManager,ViewManager是个接口,而WindowManager继承了ViewManager,WindowManagerImpl实现了WindowManager

ActivityThead.handleResumeActivity-->wm.addView-->

WindowManagerImpl.addView()--->
WindowManagerGlobal.addView-->{new ViewRootImpl(),}

ViewRootImpl.setView-->
{

1.requestLayout;

2.new InputChannel();

3.mWindowSession.addToDisplay;

4.new InputQueue();

5.mInputQueueCallback.onInputQueueCreated(mInputQueue);

6.new WindowInputEventReceiver(mInputChannel,Looper.myLooper());
}

看一下requestLayout

  @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            if (ViewDebugManager.DEBUG_REQUESTLAYOUT) {
                Log.d(mTag, "requestLayout: mView = " + mView + ", this = " + this,
                        new Throwable("requestLayout"));
            }
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }

核心是scheduleTraversals();这个方法负责刷新绘制

  void scheduleTraversals() {
        if (ViewDebugManager.DEBUG_SCHEDULETRAVERSALS)
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "scheduleTraversals In");
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            if (ViewDebugManager.DEBUG_SCHEDULETRAVERSALS)
                Trace.traceBegin(Trace.TRACE_TAG_VIEW, "scheduleTraversals occurred");
            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();
            if (ViewDebugManager.DEBUG_SCHEDULETRAVERSALS) Trace.traceEnd(Trace.TRACE_TAG_VIEW);
            pokeDrawLockIfNeeded();
        }
        if (ViewDebugManager.DEBUG_SCHEDULETRAVERSALS) Trace.traceEnd(Trace.TRACE_TAG_VIEW);
    }
    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }

 

mTraversalRunnable-->doTraversal-->performTraversals--->relayoutWindow

其中performTraversals方法开始遍历整个View树,执行View的measure,layout,draw流程  

链接:https://blog.csdn.net/chi_wy/article/details/84134320


    private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
            boolean insetsPending) throws RemoteException {

....
        if (mSurface.isValid()) {
            //获取surface下一个帧
            frameNumber = mSurface.getNextFrameNumber();
        }
....
        //relayout
        int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params,
                (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
                insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
                mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
                mPendingMergedConfiguration, mSurface);
.....

   }

/frameworks/base/services/core/java/com/android/server/wm/Session.java

  @Override
    public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
            Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
            Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
            DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
            Surface outSurface) {
...
        int res = mService.relayoutWindow(this, window, seq, attrs,
                requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
                outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
                outStableInsets, outsets, outBackdropFrame, cutout,
                mergedConfiguration, outSurface);
 
...
 }

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

  public int relayoutWindow(Session session, IWindow client, int seq, LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewVisibility, int flags,
            long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
            Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
            DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
            Surface outSurface) {
....
        synchronized(mWindowMap) {
            WindowState win = windowForClientLocked(session, client, false);
....
            if (viewVisibility != View.GONE) {
                win.setRequestedSize(requestedWidth, requestedHeight);
            }
 
            //log中输出的Relayout刷新
            if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
                    + " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
 
             win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
 
            // We should only relayout if the view is visible, it is a starting window, or the
            // associated appToken is not hidden.
            final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
                    (win.mAppToken == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
                            || !win.mAppToken.isClientHidden());
            // If we are not currently running the exit animation, we need to see about starting
            // one.
            // We don't want to animate visibility of windows which are pending replacement.
            // In the case of activity relaunch child windows could request visibility changes as
            // they are detached from the main application window during the tear down process.
            // If we satisfied these visibility changes though, we would cause a visual glitch
            // hiding the window before it's replacement was available. So we just do nothing on
            // our side.
            // This must be called before the call to performSurfacePlacement.
            if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) {
                if (DEBUG_VISIBILITY) {
                    Slog.i(TAG_WM,
                            "Relayout invis " + win + ": mAnimatingExit=" + win.mAnimatingExit);
                }
                result |= RELAYOUT_RES_SURFACE_CHANGED;
                if (!win.mWillReplaceWindow) {
                    focusMayChange = tryStartExitingAnimation(win, winAnimator, isDefaultDisplay,
                            focusMayChange);
                }
            }
            // We may be deferring layout passes at the moment, but since the client is interested
            // in the new out values right now we need to force a layout.
            mWindowPlacerLocked.performSurfacePlacement(true /* force */);
 
       }
 
 
  }

3.mWindowSession.addToDisplay;

Session.addToDisplay--->WindowManagerService.addWindow---->

    public int addWindow(Session session, IWindow client, int seq,
            LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,
            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
....
        synchronized(mWindowMap) {
....
            if (token == null) {
                token = new WindowToken(this, binder, type, false, displayContent,
                        session.mCanAddInternalSystemWindow, isRoundedCornerOverlay);

            } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
                atoken = token.asAppWindowToken();
...

            }
....

....
            mInputMonitor.setUpdateInputWindowsNeededLw();

            boolean focusChanged = false;
            if (win.canReceiveKeys()) {
                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
                        false /*updateInputWindows*/);
                if (focusChanged) {
                    imMayMove = false;
                }
            }

....
            if (imMayMove) {
                displayContent.computeImeTarget(true /* updateImeTarget */);
            }

            // Don't do layout here, the window must call
            // relayout to be displayed, so we'll do it there.
            win.getParent().assignChildLayers();

            if (focusChanged) {
                mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
            }
            mInputMonitor.updateInputWindowsLw(false /*force*/);
....

       }


        return res;
......

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章