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的显示流程。