Activity的显示

300 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第24天,点击查看活动详情

1.Activity的显示

Activity的显示原理如下图所示 在这里插入图片描述 在Activity启动的时候会创建一个PhoneWindow,而这个PhoneWindow会包含一个DecorView,DecorView就是Activity的rootview,其中包含一个bar和contentView,我们自己写的布局会放到contentView当中。对于每个DecorView都有一个对应的ViewRootImpl对象,能够和WMS进行双向通信,负责DecorView的绘制。 接着我们来看下Activity的显示流程图 在这里插入图片描述 有以下几个关键步骤需要我们关注一下

1.setContentView

以下为PhoneWindow当中的setContentView,可以看到我们自己定义的layout被夹在到了mContentParent,所以我们的方法名称才叫做setContentView,而不叫setView。

//PhoneWindow.java
public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        //1.确保decorView被创建
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }

    if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                getContext());
        transitionTo(newScene);
    } else {
        //2.将我们自己定义的layout加载到contentview当中
        mLayoutInflater.inflate(layoutResID, mContentParent);
    }
......
}

2.handleResumeActivity

如下代码为ActivityThread的handleResumeActivity方法,会触发activity的onResume周期函数。此方法中会将decorView添加到windowmanager当中,并创建ViewRootImpl对象,负责管理view的绘制,因此Activity在onResume周期函数之后才能够可见。

public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
        String reason) {
        //1.执行activity的onresume周期函数
		final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
		......
		ViewManager wm = a.getWindowManager();
		//2.将decorview添加到windowManager当中
		wm.addView(decor, l);
		 r.activity.makeVisible();
		 ......
}

3.setView

如下代码为ViewRootImpl的setView方法,如注释1所示,会先出发重绘制,然后会调用mWindowSession.addToDisplay方法,将window添加到wms,wms将会给应用分配surface,并掌管surface的尺寸和显示顺序。

ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    ......
    //1.触发重绘
	requestLayout();
	......
	//2.binder调用,wms通信
	mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
	                            getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
	                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
	                            mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
	......
}