在Android开发中,程序猿接触最多的就是Activity,其中必须会使用到的一个方法就是Activity的onCreate()方法,但是这个方法并不是程序的入口调用函数,他只是Activity的生命周期函数调用的第一个方法,而真正的程序入口在ActivityThread类的main方法.
我们看下ActivityThread的main做了那些逻辑处理
public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");SamplingProfilerIntegration.start();// CloseGuard defaults to true and can be quite spammy. We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Set the reporter for event logging in libcoreEventLogger.setReporter(new EventLoggingReporter());// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);Process.setArgV0("<pre-initialized>");//1.主线程LooperLooper.prepareMainLooper();//2.实例化ActivityThread对象,并调用attach()方法ActivityThread thread = new ActivityThread();thread.attach(false);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);//3.开启主线程Loooper轮询Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}
接着看thread.attach()方法的实现
private void attach(boolean system) {sCurrentActivityThread = this;mSystemThread = system;//system为false代表不是系统应用if (!system) {ViewRootImpl.addFirstDrawHandler(new Runnable() {@Overridepublic void run() {ensureJitEnabled();}});android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",UserHandle.myUserId());RuntimeInit.setApplicationObject(mAppThread.asBinder());//这个方法我们在上一篇博客中讲到过获取的AMS对象,然后调用了AMS的attachApplication()方法final IActivityManager mgr = ActivityManagerNative.getDefault();try {mgr.attachApplication(mAppThread);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}// Watch for getting close to heap limit.BinderInternal.addGcWatcher(new Runnable() {@Override public void run() {if (!mSomeActivitiesChanged) {return;}Runtime runtime = Runtime.getRuntime();long dalvikMax = runtime.maxMemory();long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();if (dalvikUsed > ((3*dalvikMax)/4)) {if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)+ " total=" + (runtime.totalMemory()/1024)+ " used=" + (dalvikUsed/1024));mSomeActivitiesChanged = false;try {mgr.releaseSomeActivities(mAppThread);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}}});} else {// Don't set application object here -- if the system crashes,// we can't display an alert, we just want to die die die.android.ddm.DdmHandleAppName.setAppName("system_process",UserHandle.myUserId());try {mInstrumentation = new Instrumentation();ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);mInitialApplication = context.mPackageInfo.makeApplication(true, null);mInitialApplication.onCreate();} catch (Exception e) {throw new RuntimeException("Unable to instantiate Application():" + e.toString(), e);}}// add dropbox logging to libcoreDropBox.setReporter(new DropBoxReporter());ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {@Overridepublic void onConfigurationChanged(Configuration newConfig) {synchronized (mResourcesManager) {// We need to apply this change to the resources// immediately, because upon returning the view// hierarchy will be informed about it.if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),mResourcesManager.getConfiguration().getLocales());// This actually changed the resources! Tell// everyone about it.if (mPendingConfiguration == null ||mPendingConfiguration.isOtherSeqNewer(newConfig)) {mPendingConfiguration = newConfig;sendMessage(H.CONFIGURATION_CHANGED, newConfig);}}}}@Overridepublic void onLowMemory() {}@Overridepublic void onTrimMemory(int level) {}});}
接着看AMS的attachApplication()方法-->调用的是attachApplicationLocked()
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {// Find the application record that is being attached... either via// the pid if we are running in multiple processes, or just pull the// next app record if we are emulating process with anonymous threads.ProcessRecord app;if (pid != MY_PID && pid >= 0) {synchronized (mPidsSelfLocked) {app = mPidsSelfLocked.get(pid);}} else {app = null;}if (app == null) {Slog.w(TAG, "No pending application record for pid " + pid+ " (IApplicationThread " + thread + "); dropping process");EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);if (pid > 0 && pid != MY_PID) {Process.killProcessQuiet(pid);//TODO: killProcessGroup(app.info.uid, pid);} else {try {thread.scheduleExit();} catch (Exception e) {// Ignore exceptions.}}return false;}// If this application record is still attached to a previous// process, clean it up now.if (app.thread != null) {handleAppDiedLocked(app, true, true);}// Tell the process all about itself.if (DEBUG_ALL) Slog.v(TAG, "Binding process pid " + pid + " to record " + app);final String processName = app.processName;try {AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);thread.asBinder().linkToDeath(adr, 0);app.deathRecipient = adr;} catch (RemoteException e) {app.resetPackageList(mProcessStats);startProcessLocked(app, "link fail", processName);return false;}EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);app.makeActive(thread, mProcessStats);app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;app.forcingToForeground = null;updateProcessForegroundLocked(app, false, false);app.hasShownUi = false;app.debugging = false;app.cached = false;app.killedByAm = false;// We carefully use the same state that PackageManager uses for// filtering, since we use this flag to decide if we need to install// providers when user is unlocked laterapp.unlocked = StorageManager.isUserKeyUnlocked(app.userId);mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;if (providers != null && checkAppInLaunchingProvidersLocked(app)) {Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);msg.obj = app;mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);}if (!normalMode) {Slog.i(TAG, "Launching preboot mode app: " + app);}if (DEBUG_ALL) Slog.v(TAG, "New app record " + app+ " thread=" + thread.asBinder() + " pid=" + pid);try {int testMode = IApplicationThread.DEBUG_OFF;if (mDebugApp != null && mDebugApp.equals(processName)) {testMode = mWaitForDebugger? IApplicationThread.DEBUG_WAIT: IApplicationThread.DEBUG_ON;app.debugging = true;if (mDebugTransient) {mDebugApp = mOrigDebugApp;mWaitForDebugger = mOrigWaitForDebugger;}}String profileFile = app.instrumentationProfileFile;ParcelFileDescriptor profileFd = null;int samplingInterval = 0;boolean profileAutoStop = false;if (mProfileApp != null && mProfileApp.equals(processName)) {mProfileProc = app;profileFile = mProfileFile;profileFd = mProfileFd;samplingInterval = mSamplingInterval;profileAutoStop = mAutoStopProfiler;}boolean enableTrackAllocation = false;if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {enableTrackAllocation = true;mTrackAllocationApp = null;}// If the app is being launched for restore or full backup, set it up speciallyboolean isRestrictedBackupMode = false;if (mBackupTarget != null && mBackupAppName.equals(processName)) {isRestrictedBackupMode = mBackupTarget.appInfo.uid >= Process.FIRST_APPLICATION_UID&& ((mBackupTarget.backupMode == BackupRecord.RESTORE)|| (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)|| (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL));}if (app.instrumentationClass != null) {notifyPackageUse(app.instrumentationClass.getPackageName(),PackageManager.NOTIFY_PACKAGE_USE_INSTRUMENTATION);}if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Binding proc "+ processName + " with config " + mConfiguration);ApplicationInfo appInfo = app.instrumentationInfo != null? app.instrumentationInfo : app.info;app.compat = compatibilityInfoForPackageLocked(appInfo);if (profileFd != null) {profileFd = profileFd.dup();}ProfilerInfo profilerInfo = profileFile == null ? null: new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);//1.这是个重要方法,根据名字就可以知道该方法的作用就是将ApplicationThread绑定到AMS上.thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,app.instrumentationUiAutomationConnection, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.persistent,new Configuration(mConfiguration), app.compat,getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked());updateLruProcessLocked(app, false, null);app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();} catch (Exception e) {// todo: Yikes! What should we do? For now we will try to// start another process, but that could easily get us in// an infinite loop of restarting processes...Slog.wtf(TAG, "Exception thrown during bind of " + app, e);app.resetPackageList(mProcessStats);app.unlinkDeathRecipient();startProcessLocked(app, "bind fail", processName);return false;}// Remove this record from the list of starting applications.mPersistentStartingProcesses.remove(app);if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,"Attach application locked removing on hold: " + app);mProcessesOnHold.remove(app);boolean badApp = false;boolean didSomething = false;// See if the top visible activity is waiting to run in this process...if (normalMode) {try {//2.第二个重要方法就是调用了AcitvityStackSupervisor的attachApplicationLocked()方法if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}// Find any services that should be running in this process...if (!badApp) {try {didSomething |= mServices.attachApplicationLocked(app, processName);} catch (Exception e) {Slog.wtf(TAG, "Exception thrown starting services in " + app, e);badApp = true;}}// Check if a next-broadcast receiver is in this process...if (!badApp && isPendingBroadcastProcessLocked(pid)) {try {didSomething |= sendPendingBroadcastsLocked(app);} catch (Exception e) {// If the app died trying to launch the receiver we declare it 'bad'Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);badApp = true;}}// Check whether the next backup agent is in this process...if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,"New app is backup target, launching agent for " + app);notifyPackageUse(mBackupTarget.appInfo.packageName,PackageManager.NOTIFY_PACKAGE_USE_BACKUP);try {thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,compatibilityInfoForPackageLocked(mBackupTarget.appInfo),mBackupTarget.backupMode);} catch (Exception e) {Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);badApp = true;}}if (badApp) {app.kill("error during init", true);handleAppDiedLocked(app, false, true);return false;}if (!didSomething) {updateOomAdjLocked();}return true;}
@Overridepublic final void attachApplication(IApplicationThread thread) {synchronized (this) {int callingPid = Binder.getCallingPid();final long origId = Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid);Binder.restoreCallingIdentity(origId);}}
在ActivityManagerService的attachApplication()方法中接着调用了attachApplicationLocked()为绑定Application加锁,接着调用了ApplicationThread的bindApplication()方法,将Application绑定到AMS上,最后调用的ActivityStackSupervisor的attachApplicationLocked()方法,我们接着看在该方法中处理了那些逻辑
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {final String processName = app.processName;boolean didSomething = false;for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {final ActivityStack stack = stacks.get(stackNdx);if (!isFocusedStack(stack)) {continue;}ActivityRecord hr = stack.topRunningActivityLocked();if (hr != null) {if (hr.app == null && app.uid == hr.info.applicationInfo.uid&& processName.equals(hr.processName)) {try {//真正我们要看的方法就是这个方法if (realStartActivityLocked(hr, app, true, true)) {didSomething = true;}} catch (RemoteException e) {Slog.w(TAG, "Exception in new application when starting activity "+ hr.intent.getComponent().flattenToShortString(), e);throw e;}}}}}if (!didSomething) {ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);}return didSomething;}
realStartActivityLocked()看方法名字也知道该方法的作用是真正启动Activity的方法
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,boolean andResume, boolean checkConfig) throws RemoteException {if (!allPausedActivitiesComplete()) {// While there are activities pausing we skipping starting any new activities until// pauses are complete. NOTE: that we also do this for activities that are starting in// the paused state because they will first be resumed then paused on the client side.if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,"realStartActivityLocked: Skipping start of r=" + r+ " some activities pausing...");return false;}if (andResume) {//冻结未尚未启动的其他activityr.startFreezingScreenLocked(app, 0);//标示当前app要位于前台显示mWindowManager.setAppVisibility(r.appToken, true);// 搜集启动较慢的app信息r.startLaunchTickingLocked();}// 检查配置信息if (checkConfig) {Configuration config = mWindowManager.updateOrientationFromAppTokens(mService.mConfiguration,r.mayFreezeScreenLocked(app) ? r.appToken : null);// Deferring resume here because we're going to launch new activity shortly.// We don't want to perform a redundant launch of the same record while ensuring// configurations and trying to resume top activity of focused stack.mService.updateConfigurationLocked(config, r, false, true /* deferResume */);}//设置相关参数信息
r.app = app;app.waitingToKill = null;r.launchCount++;r.lastLaunchTime = SystemClock.uptimeMillis();if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);int idx = app.activities.indexOf(r);if (idx < 0) {app.activities.add(r);}mService.updateLruProcessLocked(app, true, null);mService.updateOomAdjLocked();final TaskRecord task = r.task;if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);}final ActivityStack stack = task.stack;try {if (app.thread == null) {throw new RemoteException();}List<ResultInfo> results = null;List<ReferrerIntent> newIntents = null;if (andResume) {results = r.results;newIntents = r.newIntents;}if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,"Launching: " + r + " icicle=" + r.icicle + " with results=" + results+ " newIntents=" + newIntents + " andResume=" + andResume);if (andResume) {EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,r.userId, System.identityHashCode(r),task.taskId, r.shortComponentName);}if (r.isHomeActivity()) {// 是否是桌面activity,是的话将其添加到栈底mService.mHomeProcess = task.mActivities.get(0).app;}mService.notifyPackageUse(r.intent.getComponent().getPackageName(),PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);r.sleeping = false;r.forceNewConfig = false;mService.showUnsupportedZoomDialogIfNeededLocked(r);mService.showAskCompatModeDialogLocked(r);r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);ProfilerInfo profilerInfo = null;if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {if (mService.mProfileProc == null || mService.mProfileProc == app) {mService.mProfileProc = app;final String profileFile = mService.mProfileFile;if (profileFile != null) {ParcelFileDescriptor profileFd = mService.mProfileFd;if (profileFd != null) {try {profileFd = profileFd.dup();} catch (IOException e) {if (profileFd != null) {try {profileFd.close();} catch (IOException o) {}profileFd = null;}}}profilerInfo = new ProfilerInfo(profileFile, profileFd,mService.mSamplingInterval, mService.mAutoStopProfiler);}}}if (andResume) {app.hasShownUi = true;app.pendingUiClean = true;}app.forceProcessStateUpTo(mService.mTopProcessState);//所有信息准备完毕了,开始启动activityapp.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);if ((app.info.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {// This may be a heavy-weight process! Note that the package// manager will ensure that only activity can run in the main// process of the .apk, which is the only thing that will be// considered heavy-weight.if (app.processName.equals(app.info.packageName)) {if (mService.mHeavyWeightProcess != null&& mService.mHeavyWeightProcess != app) {Slog.w(TAG, "Starting new heavy weight process " + app+ " when already running "+ mService.mHeavyWeightProcess);}mService.mHeavyWeightProcess = app;Message msg = mService.mHandler.obtainMessage(ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);msg.obj = r;mService.mHandler.sendMessage(msg);}}} catch (RemoteException e) {if (r.launchFailed) {// This is the second time we failed -- finish activity// and give up.Slog.e(TAG, "Second failure launching "+ r.intent.getComponent().flattenToShortString()+ ", giving up", e);mService.appDiedLocked(app);stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,"2nd-crash", false);return false;}// This is the first time we failed -- restart process and// retry.app.activities.remove(r);throw e;}r.launchFailed = false;if (stack.updateLRUListLocked(r)) {Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list");}if (andResume) {// As part of the process of launching, ActivityThread also performs// a resume.stack.minimalResumeActivityLocked(r);} else {// This activity is not starting in the resumed state... which should look like we asked// it to pause+stop (but remain visible), and it has done so and reported back the// current icicle and other state.if (DEBUG_STATES) Slog.v(TAG_STATES,"Moving to PAUSED: " + r + " (starting in paused state)");r.state = PAUSED;}// Launch the new version setup screen if needed. We do this -after-// launching the initial activity (that is, home), so that it can have// a chance to initialize itself while in the background, making the// switch back to it faster and look better.if (isFocusedStack(stack)) {mService.startSetupActivityLocked();}// Update any services we are bound to that might care about whether// their client may have activities.if (r.app != null) {mService.mServices.updateServiceConnectionActivitiesLocked(r.app);}return true;}
最后调用了ApplicationThread的scheduleLaunchActivity()
@Overridepublic final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,ActivityInfo info, Configuration curConfig, Configuration overrideConfig,CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,int procState, Bundle state, PersistableBundle persistentState,List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {updateProcessState(procState, false);ActivityClientRecord r = new ActivityClientRecord();r.token = token;r.ident = ident;r.intent = intent;r.referrer = referrer;r.voiceInteractor = voiceInteractor;r.activityInfo = info;r.compatInfo = compatInfo;r.state = state;r.persistentState = persistentState;r.pendingResults = pendingResults;r.pendingIntents = pendingNewIntents;r.startsNotResumed = notResumed;r.isForward = isForward;r.profilerInfo = profilerInfo;r.overrideConfig = overrideConfig;updatePendingConfiguration(curConfig);//所有信息进行封装后,通过handler发送消息的方式来启动
sendMessage(H.LAUNCH_ACTIVITY, r);}
public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case LAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");final ActivityClientRecord r = (ActivityClientRecord) msg.obj;r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);} break;
Handler接收到消息通知后,调用handleLaunchActivity()方法启动activity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {// If we are getting ready to gc after going to the background, well// we are back active so skip it.unscheduleGcIdler();mSomeActivitiesChanged = true;if (r.profilerInfo != null) {mProfiler.setProfiler(r.profilerInfo);mProfiler.startProfiling();}// Make sure we are running with the most recent config.handleConfigurationChanged(null, null);if (localLOGV) Slog.v(TAG, "Handling launch of " + r);// 在初始化activity前进行处理WindowManagerGlobal.initialize();//真正执行activity的方法
Activity a = performLaunchActivity(r, customIntent);if (a != null) {r.createdConfig = new Configuration(mConfiguration);reportSizeConfigurations(r);Bundle oldState = r.state;handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);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.performPauseActivityIfNeeded(r, reason);// 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;}}} 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,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}}
真正启动activity的方法
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);}//拿到Component信息
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 {//通过反射方式实例化ClassLoader,然后再反射实例化activityjava.lang.ClassLoader cl = r.packageInfo.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);StrictMode.incrementExpectedActivityCount(activity.getClass());r.intent.setExtrasClassLoader(cl);r.intent.prepareToEnterProcess();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对象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 (r.overrideConfig != null) {config.updateFrom(r.overrideConfig);}if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "+ r.activityInfo.name + " with config " + config);Window window = null;if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {window = r.mPendingRemoveWindow;r.mPendingRemoveWindow = null;r.mPendingRemoveWindowManager = null;}//将application对象和activity进行绑定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);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()方法if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {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.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);}}if (!r.activity.mFinished) {activity.mCalled = false;if (r.isPersistable()) {mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState);} else {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;}
进入Instrumentation类,看下activity的oncreate方法是如何调用的
public void callActivityOnCreate(Activity activity, Bundle icicle,PersistableBundle persistentState) {prePerformCreate(activity);//activity方法调用activity.performCreate(icicle, persistentState);postPerformCreate(activity);}
final void performCreate(Bundle icicle) {restoreHasCurrentPermissionRequest(icicle);onCreate(icicle);mActivityTransitionState.readState(icicle);performCreateCommon();}
最后是我们熟悉的onCreate()方法
protected void onCreate(@Nullable Bundle savedInstanceState) {if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);if (mLastNonConfigurationInstances != null) {mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);}if (mActivityInfo.parentActivityName != null) {if (mActionBar == null) {mEnableDefaultActionBarUp = true;} else {mActionBar.setDefaultDisplayHomeAsUpEnabled(true);}}if (savedInstanceState != null) {Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);mFragments.restoreAllState(p, mLastNonConfigurationInstances != null? mLastNonConfigurationInstances.fragments : null);}mFragments.dispatchCreate();getApplication().dispatchActivityCreated(this, savedInstanceState);if (mVoiceInteractor != null) {mVoiceInteractor.attachActivity(this);}mCalled = true;}
总结:通过的源码分析,我们了解了一个应用程序的入口不是Activity的onCreate()方法,而是ActivityThread的main()方法,在该方法中会通过AMS来将ApplicationThread和ams进行绑定,之后又调用了ApplicationThread的scheduleLaunchActivity()方法通过handler发送通知实例化activity,并最后调用了Activity的onCreate()方法。