Android Activity View 加载流程

Android中View的绘制流程,始于ViewRootImpl#performTraversals,而ViewRootImpl是怎么和DecorView相关联起来的呢?
带着这样的疑问,于是对Activity两个关键方法onCreateonResume方法的流程调度进行分析,得出ActivityPhoneWindow,以及DecorViewViewRootImpl创建过程,最终解答了上面的疑问!

流程总结

Activity从创建到显示的过程,分为以下几步:

  1. ActivityThread#handleLaunchActivity开始,该方法又会调用到ActivityThread#performLaunchActivity真正创建Activity并开始启动工作。
  2. ActivityThread#performLaunchActivity的工作分为三步: 首先调用Instrumentation#newActivity来创建出一个Activity实例,在该方法实际上是通过反射来创建的Activity的实例对象;之后调用Activity实例对象的activity#attach,该方法实例化了mWindow字段,它是一个PhoneWindow对象,后面通过该对象来管理Activity页面中的视图;最后调用Instrumentation#callActivityOnCreate,该方法最终调用activity#onCreate方法,也就是生命周期方法onCreate
  3. onCreate方法中调用setContentView,该方法调用到PhoneWindow#setContentView创建一个DecorView,它是每个Activity的页面的根布局,注意此时该View还并未添加到Window窗口中。
  4. ActivityThread#handleResumeActivity,先调用activity#onResume方法,也就是生命周期方法onResume,之后通过WindowManagerImpl#addView(decorView)将前面创建的DecorView添加到Window中,此时,我们就能真正看到View了。

创建Activity

ActivityThread.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
ActivityThread.java
{
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
// window
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
// attach,创建Activity#mWindow对象。
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
// 最终调用到Activity生命周期onCreate
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
}
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
// ...
ActivityClientRecord r = performResumeActivity(token, clearHide, reason);
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
// ...
ViewManager wm = a.getWindowManager();
// 把decorView加入到ViewManager中
vm.addView(decor, l);
// 让DecorView可见,并且关联DecorView和ViewRootImpl;
r.activity.makeVisible();
}
}

Activity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Activity.java
{
private Window mWindow;
final void attach(Context context, ActivityThread aThread,,, Window window){
// 创建PhoneWindow对象
mWindow = new PhoneWindow(this, window, activityConfigCallback);
// ...
mWindow.setWindowManager((WindowManager)context.getSystemService(Context.WINDOW_SERVICE), mToken);
// 设置WindowManager,它其实是WindowManagerImpl实例对象。
mWindowManager = mWindow.getWindowManager();
}
public Window getWindow() {
return mWindow;
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// PhoneWindow#setContentView
setContentView(R.layout.activity_main);
}
// 让DecorView可见,并且关联DecorView和ViewRootImpl;
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager(); // WindowManagerImpl实例对象
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
}

设置ContentView

onCreate中调用setContentView(),设置Window将要显示的内容。Activity#setContentView实际上最终调用到的是PhoneWindow#setContentView,该方法中会初始化DecorView mDecor,它是Activity页面的rootView,它继承自FrameLayout。创建好了DecorView后,再根据layoutResourceId,将xml解析成View添加到DecorView中。

installDecor -> generateLayout -> mDecor.onResourcesLoaded

PhoneWindow.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
PhoneWindow.java
{
// This is the top-level view of the window, containing the window decor.
private DecorView mDecor;
// This is the view in which the window contents are placed. It is either
// mDecor itself, or a child of mDecor where the contents go.
ViewGroup mContentParent;
public PhoneWindow(Context context, Window preservedWindow,
ActivityConfigCallback activityConfigCallback) {
this(context);
// Only main activity windows use decor context, all the other windows depend on whatever
// context that was given to them.
mUseDecorContext = true;
if (preservedWindow != null) {
mDecor = (DecorView) preservedWindow.getDecorView();
}
}
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor(); // 初始化DecorView.
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
// 根据layoutResID加载xml布局文件
mLayoutInflater.inflate(layoutResID, mContentParent);
}
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
mDecor = generateDecor(-1);
// ...
} else {
mDecor.setWindow(this);
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
}
}
protected DecorView generateDecor(int future) {
// ...
return new DecorView(context, featureId, this, getAttributes());
}
protected ViewGroup generateLayout(DecorView decor) {
// 加载layoutResource并添加到DecorView中。
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
// contentParent为FrameLayout [id为: android.R.id.content]
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
}
private ViewRootImpl getViewRootImpl() {
if (mDecor != null) {
// ...
return mDecor.getViewRootImpl();
}
}
}

Window.java

1
2
3
4
5
6
7
8
9
10
11
12
13
Window.java
{
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
}

DecorView.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
DecorView.java
{
private PhoneWindow mWindow;
DecorView(Context context, int featureId, PhoneWindow window,
WindowManager.LayoutParams params) {
super(context);
// ...
setWindow(window);
}
void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
// load xmlLayoutResource as view
final View root = inflater.inflate(layoutResource, null);
// ...
addView(root, 0, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) root;
initializeElevation();
}
}

Activity页面可见onResume

ActivityThread#handleResumeActivity方法,将前面创建的DecorView添加到Window中,这样我们才能看到Activity的页面内容。

WindowManagerGlobal#addView中,会创建ViewRootImpl对象,并且让他和DecorView相关联。

ActivityThread.java

1
2
3
4
5
6
7
8
9
10
11
12
13
final void handleResumeActivity(IBinder token, boolean clearHide,
boolean isForward, boolean reallyResume, int seq, String reason) {
// ...
ActivityClientRecord r = performResumeActivity(token, clearHide, reason);
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
// 实际是是WindowManagerImpl实例对象
ViewManager wm = a.getWindowManager();
// 把decorView加入到ViewManager中
vm.addView(decor, l);
// 让DecorView可见,并且关联DecorView和ViewRootImpl,关键!!!
r.activity.makeVisible();
}

WindowManagerImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
WindowManagerImpl.java
{
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
# WindowManagerGlobal
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
}
WindowManagerGlobal.java
{
// 创建ViewRootImpl,并且和DecorView相关联
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
ViewRootImpl root;
// 创建ViewRootImpl
root = new ViewRootImpl(view.getContext(), display);
// ViewRootImpl#setView
root.setView(view, wparams, panelParentView);
}
}

ViewRootImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ViewRootImpl.java
{
View mView; // 实际是就是DecorView
final View.AttachInfo mAttachInfo;
public ViewRootImpl(Context context, Display display) {
mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this, context);
}
private void performTraversals() {
final View host = mView;
//
host.dispatchAttachedToWindow(mAttachInfo, 0);
}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
// 设置RootView ...
mAttachInfo.mRootView = view;
}
}
}
}

View.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
View.java
{
AttachInfo mAttachInfo;
// 设置View的AttachInfo,保存了ViewRootImpl对象引用。
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
mAttachInfo = info;
}
public ViewRootImpl getViewRootImpl() {
if (mAttachInfo != null) {
return mAttachInfo.mViewRootImpl;
}
return null;
}
AttachInfo(IWindowSession session, IWindow window, Display display,
ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer,
Context context) {
}
}

流程图

StartActivity

上图中,step3step4在真实情况下,并不是这样直接调用过去了,而是Instrumentation#execStartActivity方法,会最终调用到ActivityManagerService,AMS在创建好启动Activity所需要的相关环境后,会调用ApplicaitonThread#scheduleLaunchActivity,该方法才调用到ActivityThread#handleLaunchActivity