對接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;
......
}