8.2.2 Activity的UI绘制

ViewRoot的setView函数中会有一个requestLayout。根据前面的分析可知,它会向ViewRoot发送一个DO_TRAVERSAL消息,来看它的handleMessage函数,代码如下所示:


[—>ViewRoot.java]

public void handleMessage(Message msg){

switch(msg.what){

……

case DO_TRAVERSAL:

……

performTraversals();//调用performTraversals函数。

……

break;

……

}

}


再去看performTraversals函数,这个函数比较复杂,先只看它的关键部分,代码如下所示:


[—>ViewRoot.java]

private void performTraversals(){

final View host=mView;//还记得这mView吗?它就是DecorView哦。

boolean initialized=false;

boolean contentInsetsChanged=false;

boolean visibleInsetsChanged;

try{

relayoutResult=//①关键函数relayoutWindow。

relayoutWindow(params,viewVisibility,insetsPending);

}

……

draw(fullRedrawNeeded);//②开始绘制

……

}


1.relayoutWindow分析

performTraversals函数比较复杂,暂时只关注其中的两个函数relayoutWindow和draw即可。先看第一个relayoutWindow,代码如下所示:


[—>ViewRoot.java]

private int relayoutWindow(WindowManager.LayoutParams params,

int viewVisibility,boolean insetsPending)throws RemoteException{

//原来是调用IWindowSession的relayOut,暂且记住这个调用。

int relayoutResult=sWindowSession.relayout(

mWindow,params,

(int)(mView.mMeasuredWidth*appScale+0.5f),

(int)(mView.mMeasuredHeight*appScale+0.5f),

viewVisibility,insetsPending,mWinFrame,

mPendingContentInsets,mPendingVisibleInsets,

mPendingConfiguration,mSurface);mSurface作为参数传进去了。

}

……

}


relayoutWindow中会调用IWindowSession的relayout函数,暂且记住这个调用,在精简流程后再进行分析。

2.draw分析

再来看draw函数。这个函数非常重要,它可是Activity漂亮脸蛋的塑造大师啊,代码如下所示:


[—>ViewRoot.java]

private void draw(boolean fullRedrawNeeded){

Surface surface=mSurface;//mSurface是ViewRoot的成员变量。

……

Canvas canvas;

try{

int left=dirty.left;

int top=dirty.top;

int right=dirty.right;

int bottom=dirty.bottom;

//从mSurface中lock一块Canvas。

canvas=surface.lockCanvas(dirty);

……

mView.draw(canvas);//调用DecorView的draw函数,canvas就是画布的意思啦!

……

//unlock画布,屏幕上马上就会见到漂亮宝贝的长相了。

surface.unlockCanvasAndPost(canvas);

}

……

}


UI的显示好像很简单嘛!真的是这样的吗?在揭露这个“惊天秘密”之前我们先总结一下Activity的显示流程。