前言
我们知道AMS启动一个APP(Launcher——>AMS—>MyAPP)会创建ActivityThread。也就是ActivityThread是一个App的真正入口,分析View的绘制流程,我们肯定是以ActivityThread为起点来分析。然后抵达一个方法performTraversals
。这个方法是ViewRoot内的一个方法,也是View绘制的真实起点。我们先不讨论它们的具体,本文主要目的是看在它被执行之前都经历了哪些流程。
参考1.Launcher启动流程及初始化
参考2.ActivityThread分析—ActivityThread的main方法是如何被调用的
参考3.ActivityThread分析—ActivityThread的main方法的执行流程分析
代码分析
frameworks\base\core\java\android\app\ActivityThread.java#handleResumeActivity()
wm是WindowManger,其实现类为WindowMangerImpl,我们去看它的addView方法。
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
......
if (r != null) {
......
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
......
} else {
......
}
}
frameworks\base\core\java\android\view\WindowManagerImpl.java#addView()
尾部调用了 ViewRoot root.setView(view, wparams, panelParentView);
private void addView(View view, ViewGroup.LayoutParams params, boolean nest)
{
if (Config.LOGV) Log.v("WindowManager", "addView view=" + view);
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException(
"Params must be WindowManager.LayoutParams");
}
final WindowManager.LayoutParams wparams
= (WindowManager.LayoutParams)params;
ViewRoot root;
View panelParentView = null;
synchronized (this) {
// Here's an odd/questionable case: if someone tries to add a
// view multiple times, then we simply bump up a nesting count
// and they need to remove the view the corresponding number of
// times to have it actually removed from the window manager.
// This is useful specifically for the notification manager,
// which can continually add/remove the same view as a
// notification gets updated.
......
}
// do this last because it fires off messages to start doing things
root.setView(view, wparams, panelParentView);
}
frameworks\base\core\java\android\view\ViewRoot#setView()
/**
* We have one child
*/
public void setView(View view, WindowManager.LayoutParams attrs,
View panelParentView) {
synchronized (this) {
if (mView == null) {
......
// 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();
......
}
}
}
frameworks\base\core\java\android\view\ViewRoot#requestLayout()
/**
* {@inheritDoc}
*/
public void requestLayout() {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
frameworks\base\core\java\android\view\ViewRoot#scheduleTraversals()
到这里发了一个handler,由于ViewRoot自身继承了handler,所以会发送到它的handlerMessage方法。
public void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
sendEmptyMessage(DO_TRAVERSAL);
}
}
frameworks\base\core\java\android\view\ViewRoot#handleMessage()
可以看到这里就调用了performTraversals();方法,点进去看。
public void handleMessage(Message msg) {
...
case DO_TRAVERSAL:
if (mProfile) {
Debug.startMethodTracing("ViewRoot");
}
performTraversals();//这里
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
break;
...
}
frameworks\base\core\java\android\view\ViewRoot#ViewRootImpl()
注意这3个perform的顺序,另外源码版本太低是没有这3个方法的(我的是2.3居然找不出这3个方法,后来去studio内看哎看见),哎可把我一阵好找。
private void performTraversals() {
......
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
...
performLayout(lp, desiredWindowWidth, desiredWindowHeight);
...
performDraw()
......
}