Activity界面加载流程

我们都知道在Activity的OnCreate()方法中调用了setContentView()去添加我们的layout,不调用它就看不到界面了,我们来看一下这个方法究竟做了什么,Activity的界面是如何加载的。

protected void onCreate(Bundle savedInstanceState) {
   
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
}

进到setContentView()方法。

public void setContentView(@LayoutResintlayoutResID){
   
	getWindow().setContentView(layoutResID);
	initWindowDecorActionBar();
}

调用getWindow的setContentView,先看一下getWindow()。

private Window mWindow;
...
public Window getWindow(){
   
	return mWindow;
}

返回一个mWindow实例,这个mWindow是在哪里赋值的。
在Activity的启动流程中,我们知道最终会调用ActivityThread类的performLaunchActivity()方法创建Activity实例,接着调用activity的attach方法,最后调用OnCreate()方法。我们进到Activity类的attach()方法看一下。

final void attach(Context context, ActivityThread aThread,
		Instrumentation instr, IBinder token, int ident,
		Application application, Intent intent, ActivityInfo info,
		CharSequence title, Activity parent, String id,
		NonConfigurationInstances lastNonConfigurationInstances,
		Configuration config, String referrer, IVoiceInteractor voiceInteractor,
		Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
   
	attachBaseContext(context);

	mFragments.attachHost(null /*parent*/);
	//创建PhoneWindow,这里传入的window是null
	mWindow = new PhoneWindow(this, window, activityConfigCallback);
	mWindow.setWindowControllerCallback(this);
	mWindow.setCallback(this);
	mWindow.setOnWindowDismissedCallback(this);
	mWindow.getLayoutInflater().setPrivateFactory(this);
	if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
   
		mWindow.setSoftInputMode(info.softInputMode);
	}
	if (info.uiOptions != 0) {
   
		mWindow.setUiOptions(info.uiOptions);
	}
	...
}

创建了一个PhoneWindow,并赋值给mWindow。所以前面通过getWindow()得到的是一个PhoneWindow实例。创建PhoneWindow时做了什么,看一下PhoneWindow的构造函数。

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;
	//preservedWindow为null,不会为mDecor赋值
	if (preservedWindow != null) {
   
		mDecor = (DecorView) preservedWindow.getDecorView();
		mElevation = preservedWindow.getElevation();
		mLoadElevation = false;
		mForceDecorInstall = true;
		// If we're preserving window, carry over the app token from the preserved
		// window, as we'll be skipping the addView in handleResumeActivity(), and
		// the token will not be updated as for a new window.
		getAttributes().token = preservedWindow.getAttributes().token;
	}
	// Even though the device doesn't support picture-in-picture mode,
	// an user can force using it through developer options.
	boolean forceResizable = Settings.Global.getInt(context.getContentResolver(),
			DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
	mSupportsPictureInPicture = forceResizable || context.getPackageManager().hasSystemFeature(
			PackageManager.FEATURE_PICTURE_IN_PICTURE);
	mActivityConfigCallback = activityConfigCallback;
}

因为preservedWindow为空,不会执行if中的代码,到这里mDecor还没有被赋值。
继续看代码,现在我们知道了是调用了PhoneWindow的setContentView()方法。

@Override
public void setContentView(int layoutResID) {
   
	// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
	// decor, when theme attributes and the like are crystalized. Do not check the feature
	// before this happens.
	if (mContentParent == null) {
   
		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 {
   
		mLayoutInflater.inflate(layoutResID, mContentParent);
	}
	mContentParent.requestApplyInsets();
	final Callback cb = getCallback();
	if (cb != null && !isDestroyed()) {
   
		cb.onContentChanged();
	}
	mContentParentExplicitlySet = true;
}

第一次加载时mContentParent为空,会执行installDecor()方法。


                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值