Android源碼分析-Activity的啓動過程

轉載請註明出處: http://blog.csdn.net/singwhatiwanna/article/details/18154335

前言

Activity是Android中一個很重要的概念,堪稱四大組件之首,關於Activity有不少內容,好比生命週期和啓動Flags,這兩者想要說清楚,恐怕又要寫兩篇長文,更況且分析它們的源碼呢。不過本文的側重點不是它們,我要介紹的是一個Activity典型的啓動過程,本文會從源碼的角度對其進行分析。咱們知道,當startActivity被調用的時候,能夠啓動一個Activity,可是你知道這個Activity是如何被啓動的嗎?每一個Activity也是一個對象,你知道這個對象是啥時候被建立的嗎(也就是說它的構造方法是何時被調用的)?爲何onCreate是Activity的執行入口?全部的這一切都被系統封裝好了,對咱們來講是透明的,咱們使用的時候僅僅是傳遞一個intent而後startActivity就能夠達到目的了,不過,閱讀了本文之後,你將會了解它的背後到底作了哪些事情。在分析以前,我先介紹幾個類:java

  1. Activity:這個你們都熟悉,startActivity方法的真正實如今Activity中
  2. Instrumentation:用來輔助Activity完成啓動Activity的過程
  3. ActivityThread(包含ApplicationThread + ApplicationThreadNative + IApplicationThread):真正啓動Activity的實現都在這裏

源碼分析

首先看入口windows

code:Activity#startActivityapp

@Override
public void startActivity(Intent intent) {
	startActivity(intent, null);
}

@Override
public void startActivity(Intent intent, Bundle options) {
	if (options != null) {
		startActivityForResult(intent, -1, options);
	} else {
		// Note we want to go through this call for compatibility with
		// applications that may have overridden the method.
		startActivityForResult(intent, -1);
	}
}

public void startActivityForResult(Intent intent, int requestCode) {
	startActivityForResult(intent, requestCode, null);
}

說明:顯然,從上往下,最終都是由startActivityForResult來實現的ide

接着看源碼分析

code:Activity#startActivityForResultthis

public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
	//通常的Activity其mParent爲null,mParent經常使用在ActivityGroup中,ActivityGroup已廢棄
	if (mParent == null) {
		//這裏會啓動新的Activity,核心功能都在mMainThread.getApplicationThread()中完成
		Instrumentation.ActivityResult ar =
			mInstrumentation.execStartActivity(
				this, mMainThread.getApplicationThread(), mToken, this,
				intent, requestCode, options);
		if (ar != null) {
		    //發送結果,即onActivityResult會被調用
			mMainThread.sendActivityResult(
				mToken, mEmbeddedID, requestCode, ar.getResultCode(),
				ar.getResultData());
		}
		if (requestCode >= 0) {
			// If this start is requesting a result, we can avoid making
			// the activity visible until the result is received.  Setting
			// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
			// activity hidden during this time, to avoid flickering.
			// This can only be done when a result is requested because
			// that guarantees we will get information back when the
			// activity is finished, no matter what happens to it.
			mStartedActivity = true;
		}

		final View decor = mWindow != null ? mWindow.peekDecorView() : null;
		if (decor != null) {
			decor.cancelPendingInputEvents();
		}
		// TODO Consider clearing/flushing other event sources and events for child windows.
	} else {
		//在ActivityGroup內部的Activity調用startActivity的時候會走到這裏,內部處理邏輯和上面是相似的
		if (options != null) {
			mParent.startActivityFromChild(this, intent, requestCode, options);
		} else {
			// Note we want to go through this method for compatibility with
			// existing applications that may have overridden it.
			mParent.startActivityFromChild(this, intent, requestCode);
		}
	}
}

說明:上述代碼關鍵點都有註釋了,能夠發現,真正打開activity的實如今Instrumentation的execStartActivity方法中,去看看spa

code:Instrumentation#execStartActivity.net

public ActivityResult execStartActivity(
		Context who, IBinder contextThread, IBinder token, Activity target,
		Intent intent, int requestCode, Bundle options) {
	//核心功能在這個whoThread中完成,其內部scheduleLaunchActivity方法用於完成activity的打開
	IApplicationThread whoThread = (IApplicationThread) contextThread;
	if (mActivityMonitors != null) {
		synchronized (mSync) {
			//先查找一遍看是否存在這個activity
			final int N = mActivityMonitors.size();
			for (int i=0; i<N; i++) {
				final ActivityMonitor am = mActivityMonitors.get(i);
				if (am.match(who, null, intent)) {
					//若是找到了就跳出循環
					am.mHits++;
					//若是目標activity沒法打開,直接return
					if (am.isBlocking()) {
						return requestCode >= 0 ? am.getResult() : null;
					}
					break;
				}
			}
		}
	}
	try {
		intent.migrateExtraStreamToClipData();
		intent.prepareToLeaveProcess();
		//這裏纔是真正打開activity的地方,核心功能在whoThread中完成。
		int result = ActivityManagerNative.getDefault()
			.startActivity(whoThread, who.getBasePackageName(), intent,
					intent.resolveTypeIfNeeded(who.getContentResolver()),
					token, target != null ? target.mEmbeddedID : null,
					requestCode, 0, null, null, options);
		//這個方法是專門拋異常的,它會對結果進行檢查,若是沒法打開activity,
		//則拋出諸如ActivityNotFoundException相似的各類異常
		checkStartActivityResult(result, intent);
	} catch (RemoteException e) {
	}
	return null;
}

說明:我想再說一下這個方法checkStartActivityResult,它也專業拋異常的,看代碼,相信你們對下面的異常信息不陌生吧,就是它乾的,其中最熟悉的非Unable to find explicit activity class莫屬了,若是你在xml中沒有註冊目標activity,此異常將會拋出。rest

/*package*/ static void checkStartActivityResult(int res, Object intent) {
        if (res >= ActivityManager.START_SUCCESS) {
            return;
        }
        
        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException(
                        "FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException(
                        "PendingIntent is not an activity");
            default:
                throw new AndroidRuntimeException("Unknown error code "
                        + res + " when starting " + intent);
        }
    }

接下來咱們要去看看IApplicationThread,由於核心功能由其內部的scheduleLaunchActivity方法來完成,因爲IApplicationThread是個接口,因此,咱們須要找到它的實現類,我已經幫你們找到了,它就是ActivityThread中的內部類ApplicationThread,看下它的繼承關係:code

private class ApplicationThread extends ApplicationThreadNative;

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread;

能夠發現,ApplicationThread仍是間接實現了IApplicationThread接口,先看下這個類的結構

看完ApplicationThread的大體結構,咱們應該可以猜想到,Activity的生命週期中的resume、newIntent、pause、stop等事件都是由它觸發的,事實上,的確是這樣的。這裏,咱們爲了說明問題,僅僅看scheduleLaunchActivity方法

code:ApplicationThread#scheduleLaunchActivity

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
		ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
		int procState, Bundle state, List<ResultInfo> pendingResults,
		List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
		String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {

	updateProcessState(procState, false);

	ActivityClientRecord r = new ActivityClientRecord();

	r.token = token;
	r.ident = ident;
	r.intent = intent;
	r.activityInfo = info;
	r.compatInfo = compatInfo;
	r.state = state;

	r.pendingResults = pendingResults;
	r.pendingIntents = pendingNewIntents;

	r.startsNotResumed = notResumed;
	r.isForward = isForward;

	r.profileFile = profileName;
	r.profileFd = profileFd;
	r.autoStopProfiler = autoStopProfiler;

	updatePendingConfiguration(curConfig);

	queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}

說明:上述代碼很好理解,構造一個activity記錄,而後發送一個消息,因此,咱們要看看Handler是如何處理這個消息的,如今轉到這個Handler,它有個很短的名字叫作H

code:ActivityThread#H

//這個類太長,我只帖出了咱們用到的部分
private class H extends Handler {

	public void handleMessage(Message msg) {
		if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
		switch (msg.what) {
			//這裏處理LAUNCH_ACTIVITY消息類型
			case LAUNCH_ACTIVITY: {
				Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
				ActivityClientRecord r = (ActivityClientRecord)msg.obj;

				r.packageInfo = getPackageInfoNoCheck(
						r.activityInfo.applicationInfo, r.compatInfo);
				//這裏處理startActivity消息
				handleLaunchActivity(r, null);
				Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
			} break;
			case RELAUNCH_ACTIVITY: {
				Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
				ActivityClientRecord r = (ActivityClientRecord)msg.obj;
				handleRelaunchActivity(r);
				Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
			} break;
			case PAUSE_ACTIVITY:
				Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
				handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
				maybeSnapshot();
				Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
				break;
			...
		}
}

說明:看來還要看handleLaunchActivity

code:ActivityThread#handleLaunchActivity

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
	// If we are getting ready to gc after going to the background, well
	// we are back active so skip it.
	unscheduleGcIdler();

	if (r.profileFd != null) {
		mProfiler.setProfiler(r.profileFile, r.profileFd);
		mProfiler.startProfiling();
		mProfiler.autoStopProfiler = r.autoStopProfiler;
	}

	// Make sure we are running with the most recent config.
	handleConfigurationChanged(null, null);

	if (localLOGV) Slog.v(
		TAG, "Handling launch of " + r);
	//終於到底了,你們都有點不耐煩了吧,從方法名能夠看出,
	//performLaunchActivity真正完成了activity的調起,
	//同時activity會被實例化,而且onCreate會被調用
	Activity a = performLaunchActivity(r, customIntent);

	if (a != null) {
		r.createdConfig = new Configuration(mConfiguration);
		Bundle oldState = r.state;
		//看到沒,目標activity的onResume會被調用
		handleResumeActivity(r.token, false, r.isForward,
				!r.activity.mFinished && !r.startsNotResumed);

		if (!r.activity.mFinished && r.startsNotResumed) {
			// The activity manager actually wants this one to start out
			// paused, because it needs to be visible but isn't in the
			// foreground.  We accomplish this by going through the
			// normal startup (because activities expect to go through
			// onResume() the first time they run, before their window
			// is displayed), and then pausing it.  However, in this case
			// we do -not- need to do the full pause cycle (of freezing
			// and such) because the activity manager assumes it can just
			// retain the current state it has.
			try {
				r.activity.mCalled = false;
				//同時,因爲新activity被調起了,原activity的onPause會被調用
				mInstrumentation.callActivityOnPause(r.activity);
				// We need to keep around the original state, in case
				// we need to be created again.  But we only do this
				// for pre-Honeycomb apps, which always save their state
				// when pausing, so we can not have them save their state
				// when restarting from a paused state.  For HC and later,
				// we want to (and can) let the state be saved as the normal
				// part of stopping the activity.
				if (r.isPreHoneycomb()) {
					r.state = oldState;
				}
				if (!r.activity.mCalled) {
					throw new SuperNotCalledException(
						"Activity " + r.intent.getComponent().toShortString() +
						" did not call through to super.onPause()");
				}

			} catch (SuperNotCalledException e) {
				throw e;

			} catch (Exception e) {
				if (!mInstrumentation.onException(r.activity, e)) {
					throw new RuntimeException(
							"Unable to pause activity "
							+ r.intent.getComponent().toShortString()
							+ ": " + e.toString(), e);
				}
			}
			r.paused = true;
		}
	} else {
		// If there was an error, for any reason, tell the activity
		// manager to stop us.
		try {
			ActivityManagerNative.getDefault()
				.finishActivity(r.token, Activity.RESULT_CANCELED, null);
		} catch (RemoteException ex) {
			// Ignore
		}
	}
}

說明:關於原activity和新activity之間的狀態同步,若是你們感興趣能夠本身研究下,由於邏輯太複雜,我無法把全部問題都說清楚,不然就太深刻細節而淹沒了總體邏輯,研究源碼要的就是清楚總體邏輯。下面看最後一個方法,這個方法是activity的啓動過程的真正實現。
code:ActivityThread#performLaunchActivity

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
	// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

	ActivityInfo aInfo = r.activityInfo;
	if (r.packageInfo == null) {
		r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
				Context.CONTEXT_INCLUDE_CODE);
	}
	//首先從intent中解析出目標activity的啓動參數
	ComponentName component = r.intent.getComponent();
	if (component == null) {
		component = r.intent.resolveActivity(
			mInitialApplication.getPackageManager());
		r.intent.setComponent(component);
	}

	if (r.activityInfo.targetActivity != null) {
		component = new ComponentName(r.activityInfo.packageName,
				r.activityInfo.targetActivity);
	}

	Activity activity = null;
	try {
		java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
		//用ClassLoader(類加載器)將目標activity的類經過類名加載進來並調用newInstance來實例化一個對象
		//其實就是經過Activity的無參構造方法來new一個對象,對象就是在這裏new出來的。
		activity = mInstrumentation.newActivity(
				cl, component.getClassName(), r.intent);
		StrictMode.incrementExpectedActivityCount(activity.getClass());
		r.intent.setExtrasClassLoader(cl);
		if (r.state != null) {
			r.state.setClassLoader(cl);
		}
	} catch (Exception e) {
		if (!mInstrumentation.onException(activity, e)) {
			throw new RuntimeException(
				"Unable to instantiate activity " + component
				+ ": " + e.toString(), e);
		}
	}

	try {
		Application app = r.packageInfo.makeApplication(false, mInstrumentation);

		if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
		if (localLOGV) Slog.v(
				TAG, r + ": app=" + app
				+ ", appName=" + app.getPackageName()
				+ ", pkg=" + r.packageInfo.getPackageName()
				+ ", comp=" + r.intent.getComponent().toShortString()
				+ ", dir=" + r.packageInfo.getAppDir());

		if (activity != null) {
			Context appContext = createBaseContextForActivity(r, activity);
			CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
			Configuration config = new Configuration(mCompatConfiguration);
			if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
					+ r.activityInfo.name + " with config " + config);
			activity.attach(appContext, this, getInstrumentation(), r.token,
					r.ident, app, r.intent, r.activityInfo, title, r.parent,
					r.embeddedID, r.lastNonConfigurationInstances, config);

			if (customIntent != null) {
				activity.mIntent = customIntent;
			}
			r.lastNonConfigurationInstances = null;
			activity.mStartedActivity = false;
			int theme = r.activityInfo.getThemeResource()
			if (theme != 0) {
				activity.setTheme(theme);
			}

			activity.mCalled = false;
			//目標activity的onCreate被調用了,到此爲止,Activity被啓動了,接下來的流程就是Activity的生命週期了,
			//本文以前已經提到,其生命週期的各類狀態的切換由ApplicationThread內部來完成
			mInstrumentation.callActivityOnCreate(activity, r.state);
			if (!activity.mCalled) {
				throw new SuperNotCalledException(
					"Activity " + r.intent.getComponent().toShortString() +
					" did not call through to super.onCreate()");
			}
			r.activity = activity;
			r.stopped = true;
			if (!r.activity.mFinished) {
				activity.performStart();
				r.stopped = false;
			}
			if (!r.activity.mFinished) {
				if (r.state != null) {
					mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
				}
			}
			if (!r.activity.mFinished) {
				activity.mCalled = false;
				mInstrumentation.callActivityOnPostCreate(activity, r.state);
				if (!activity.mCalled) {
					throw new SuperNotCalledException(
						"Activity " + r.intent.getComponent().toShortString() +
						" did not call through to super.onPostCreate()");
				}
			}
		}
		r.paused = true;

		mActivities.put(r.token, r);

	} catch (SuperNotCalledException e) {
		throw e;

	} catch (Exception e) {
		if (!mInstrumentation.onException(activity, e)) {
			throw new RuntimeException(
				"Unable to start activity " + component
				+ ": " + e.toString(), e);
		}
	}

	return activity;
}

總結

相信當你看到這裏的時候,你對Activity的啓動過程應該有了一個感性的認識。Activity很複雜,特性不少,本文無法對各個細節進行深刻分析,並且就算真的對各個細節都進行了深刻分析,那文章要有多長啊,還有人有耐心看下去嗎?但願本文可以給你們帶來一些幫助,謝謝你們閱讀。 

相關文章
相關標籤/搜索