在前一篇博客Android O: View的绘制流程(一): 创建和加载中,
我们分析了系统创建和加载View的过程,这部分内容完成了View绘制的前置工作。
本文开始分析View的测量的流程。
一、绘制流程的起点
在分析View的测量的流程前,我们先来寻找一下界面绘制流程的起点。
当Activity启动时,会调用ActivityThread的handleLaunchActivity方法:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
............
//这部分代码,会调用Activity的onCreate, 进而调用setContentView
//完成上一篇博客描述的前置工作
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
.............
//重点关注该函数
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
.............
} else {
.............
}
}
我们跟进一下handleResumeActivity函数:
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
..........
// 会回调Activity的onResume接口
r = performResumeActivity(token, clearHide, reason);
if (r != null) {
final Activity a = r.activity;
.........
if (r.window == null && !a.mFinished && willBeVisible) {
//之前已经创建出Activity对应的PhoneWindow和DecorView
//将这些对象记录到ActivityRecord中
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
//得到WindowManagerImpl
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
..........
//如果Activity可见
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
//Activity的DecorView递交给WindowManager
wm.addView(decor, l);
} else {
...........
}
}
} else if (...) {
.......
}
.......
} else {
.........
}
}
从上述代码可以看出,解析完XML对应的View后,
最终将DecorView递交给WindowManager。
我们跟进一下WindowManagerImpl中的addView函数:
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
//实际上定义于WindowManagerGlobal中
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
继续跟进WindowManagerGlobal中的代码:
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
............
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
//进一步调整wparams
.............
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock)