第一次
Activity的显示是在onResume()之后这一点大家都知道,代码在ActivityThread中,还是不去管Activity的启动过程,只去看一下在没有setContentView的时候decorView这里是怎么添加的并且第一调用performTraversals()的。
在ActivityThread.java中,代码
handleResumeActivity()函数中调用wm.addView(decor, l);将decorView添加。
在WindowManagerImpl代码如下
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
在WindowManagerGlobal代码太多不粘贴了有这样的调用
view.setLayoutParams(wparams);
点进入之后
public void setLayoutParams(ViewGroup.LayoutParams params) {
if (params == null) {
throw new NullPointerException("Layout parameters cannot be null");
}
mLayoutParams = params;
resolveLayoutParams();
if (mParent instanceof ViewGroup) {
((ViewGroup) mParent).onSetLayoutParams(this, params);
}
requestLayout();
}
最后这句requestLayout(),这应该是第一回的调用吧。点进去
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
这里mParent就是ViewRootImp看一下这个调用
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
调用如下代码
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
post这个Runnable
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
继续调用就到了熟悉的代码了,performTraversals()。
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
第二次
WindowManagerGlobal中接下来调用ViewRootImpl 的setView
root.setView(view, wparams, panelParentView);
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout();
这里注释写到,是第一次的layout,在Window还没有添加之前的调用。然后才添加Window到界面上
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);