首先从Activity#setContentView(layoutResID)–>PhoneWindow#setContentView(layoutResID)–>然后执行 installDecor(), mLayoutInflater.inflate(layoutResID, mContentParent),
在installDecor()中会执行,generateDecor()实例化Decor, mContentParent=generateLayout(mDecor)给mContentParent赋值,根据不同的主题,获取不同的布局,比如布局screen_simple.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<ViewStub android:id="@+id/action_mode_bar_stub"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/actionBarTheme" />
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foregroundInsidePadding="false"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
获取到布局之后
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
将该布局添加到mDecor中
之后
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
将布局中的FrameLayout赋给contentParent,故
mLayoutInflater.inflate(layoutResID, mContentParent)将 layoutResId的布局添加到mContentparent中,即在Activity#setContentView(layoutResID),最后其实是将布局添加到了DecorView的id为content的FrameLayout中
然后开始View的绘制:
在ActivityThread中类H继承自Handler, 在其handleMessage中,收到LAUNCH_ACTIVITY 的指令后,开始执行handleLaunchActivity()–>handleResumeActivity()–>WindowManagerImpl#addView(decor, l)–>WindowManagerGlobal#addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) -->ViewRootImpl#setView(view, wparams, panelParentView)将decorview和ViewRootImpl进行关联
绘制的类及方法:
ViewRootImpl#setView(view, wparams, panelParentView)–>requestLayout()
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
先检查是否在主线程,不在就抛异常,在就执行scheduleTraversals()
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);的参数mTraversalRunnable是一个线程,其中执行了 doTraversal()方法
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
doTraversal中执行performTraversals(),在performTraversals()中开启绘制的三大步骤:
测量:ViewRootImpl#performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);-->mView.measure()
布局:ViewRootImpl#performLayout(lp, mWidth, mHeight);-->host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
绘制:ViewRootImpl#performDraw();-->draw(fullRedrawNeeded)-->drawSoftware-->mView.draw(canvas);
performMeasure中的参数
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
让我们看看getRootMeasureSpec方法
private static int getRootMeasureSpec(int windowSize, int rootDimension) {
int measureSpec;
switch (rootDimension) {
case ViewGroup.LayoutParams.MATCH_PARENT:
// Window can't resize. Force root view to be windowSize.
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
break;
case ViewGroup.LayoutParams.WRAP_CONTENT:
// Window can resize. Set max size for root view.
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
break;
default:
// Window wants to be an exact size. Force root view to be that size.
measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
break;
}
return measureSpec;
}
根据窗口大小和子View的LayoutParams来确定子View的MeasureSpec .接着执行mView.measure(),会跳转到View的measure方法,接着会执行onMeasure,因为DecorView继承自FrameLayout,所以会执行FrameLayout#onMeasure,
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (mMeasureAllChildren || child.getVisibility() != GONE) {
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
maxWidth = Math.max(maxWidth,
child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
maxHeight = Math.max(maxHeight,
child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
childState = combineMeasuredStates(childState, child.getMeasuredState());
if (measureMatchParentChildren) {
if (lp.width == LayoutParams.MATCH_PARENT ||
lp.height == LayoutParams.MATCH_PARENT) {
mMatchParentChildren.add(child);
}
}
}
}
……
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
resolveSizeAndState(maxHeight, heightMeasureSpec,
childState << MEASURED_HEIGHT_STATE_SHIFT));
先调用measureChildWithMargins 循环测量子View的大小,最后设置自身的大小。再看看measureChildWithMargins的实现
protected void measureChildWithMargins(View child,
int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
+ widthUsed, lp.width);
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
+ heightUsed, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
getChildMeasureSpec的规则如下图所示
先获取子View的MeasureSpec,然后调用子View的child.measure(childWidthMeasureSpec, childHeightMeasureSpec);这样绘制就从父容器传递到了子容器。
再看看View的onMeasure的实现
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
setMeasuredDimension:
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
boolean optical = isLayoutModeOptical(this);
if (optical != isLayoutModeOptical(mParent)) {
Insets insets = getOpticalInsets();
int opticalWidth = insets.left + insets.right;
int opticalHeight = insets.top + insets.bottom;
measuredWidth += optical ? opticalWidth : -opticalWidth;
measuredHeight += optical ? opticalHeight : -opticalHeight;
}
setMeasuredDimensionRaw(measuredWidth, measuredHeight);
}
setMeasuredDimensionRaw:
private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
mMeasuredWidth = measuredWidth;
mMeasuredHeight = measuredHeight;
mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
}
最后只是给mMeasureWidth,mMeasureHeight赋值
汇总一下整个过程:
ViewRootImpl#setView()–>ViewRootImpl#requestLayout()–>scheduleTraversals()–>doTraversal()–>performTraversals–>ViewRootImpl#performMeasure#FrameLayout#measure(), measure中会调用onMeasure,onMeasure会对每个子View进行measure()过程,然后设置自己的测量大小。View的measure不用测量子View,直接设置自身的大小。
而layout过程与此类似:
mView.layout()–>FrameLayout#layout()–>FrameLayout#setFrame(),onLayout()–>FrameLayout#layoutChildren–>child.layout()–>View#layout(),View的layou会设置自身边界,其onLayout是个空实现。
draw过程:
mView.draw()–>View#draw
* 1. Draw the background
* 2. If necessary, save the canvas' layers to prepare for fading
* 3. Draw view's content
* 4. Draw children
* 5. If necessary, draw the fading edges and restore layers
* 6. Draw decorations (scrollbars for instance)
View#dispatchDraw()–>ViewGroup#dispatchDraw()–>ViewGroup#drawChild()–>child.draw() ,至此绘制也传到了子容器。
我也很蒙蔽