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

}

 

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