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