2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Activity启动过程源码分析

Activity启动过程源码分析

时间:2020-02-19 14:17:59

相关推荐

Activity启动过程源码分析

老罗的Android系统源码分析讲的很不错,网上有很不同层面多源码分析。了解细节,还是自己看源码最直接。个人并没有透彻的研究过Android系统,这一系列的博客就当是读Android源码笔记了。有不对的地方还请多指教。

startActivity方法

context调用startActivity()实际是调用了ContextImpl的startActivity()方法,

@Overridepublic void startActivity(Intent intent, Bundle options) {warnIfCallingFromSystemProcess();if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {throw new AndroidRuntimeException("Calling startActivity() from outside of an Activity "+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."+ " Is this really what you want?");}mMainThread.getInstrumentation().execStartActivity(getOuterContext(), mMainThread.getApplicationThread(), null,(Activity)null, intent, -1, options);}

在这里看到了FLAG_ACTIVITY_NEW_TASK这个标志位的判断,如果调用startActivity的对象不是一个Activity,就需要加FLAG_ACTIVITY_NEW_TASK这个标志,否则会抛出异常。 Activity调用startActivity()最终是调用了startActivityForResult()方法

public void startActivityForResult(Intent intent, int requestCode, Bundle options) {if (mParent == null) {Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);if (ar != null) {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;}} else {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);}}}

最终都是调用Instrumentation的execStartActivity()方法

public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {IApplicationThread whoThread = (IApplicationThread) contextThread;if (mActivityMonitors != null) {synchronized (mSync) {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++;if (am.isBlocking()) {return requestCode >= 0 ? am.getResult() : null;}break;}}}}try {intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess();int result = ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, null, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {}return null;}

ActivityManagerNative是一个Binder,调用ActivityManagerNative的getDefault获取ActivityManagerService的一个代理对象,通过调用StartActivity来通知ActivityManagerService将一个Acitivity组件启动起来。

ActivityManagerService

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags,String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {enforceNotIsolatedCaller("startActivity");userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,false, true, "startActivity", null);return mMainStack.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,null, null, options, userId);}

mMainStack用来描述一个Activity组件栈 startActivityMayWait方法首先解析了启动Activity组件的更多信息

final int startActivityMayWait(IApplicationThread caller, int callingUid,String callingPackage, Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags, String profileFile,ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,Bundle options, int userId) {// Refuse possible leaked file descriptorsif (intent != null && intent.hasFileDescriptors()) {throw new IllegalArgumentException("File descriptors passed in Intent");}boolean componentSpecified = intent.getComponent() != null;// Don't modify the client's object!intent = new Intent(intent);// Collect information about the target of the Intent.ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,profileFile, profileFd, userId);

调用startActivityLocked这个方法继续

int res = startActivityLocked(caller, intent, resolvedType,aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,callingPackage, startFlags, options, componentSpecified, null);if (mConfigWillChange && mMainStack) {// If the caller also wants to switch to a new configuration,// do so now. This allows a clean switch, as we are waiting// for the current activity to pause (so we will not destroy// it), and have not yet started the next activity.mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,"updateConfiguration()");mConfigWillChange = false;if (DEBUG_CONFIGURATION) Slog.v(TAG,"Updating to new configuration after starting activity.");mService.updateConfigurationLocked(config, null, false, false);}Binder.restoreCallingIdentity(origId);

startActivityLocked中更新了ActivityRecord,调用startActivityUncheckedLocked进一步启动目标Acitivy

if (mMainStack) {if (mResumedActivity == null|| mResumedActivity.info.applicationInfo.uid != callingUid) {if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {PendingActivityLaunch pal = new PendingActivityLaunch();pal.r = r;pal.sourceRecord = sourceRecord;pal.startFlags = startFlags;mService.mPendingActivityLaunches.add(pal);mDismissKeyguardOnNextActivity = false;ActivityOptions.abort(options);return ActivityManager.START_SWITCHES_CANCELED;}}if (mService.mDidAppSwitch) {// This is the second allowed switch since we stopped switches,// so now just generally allow switches. Use case: user presses// home (switches disabled, switch to home, mDidAppSwitch now true);// user taps a home icon (coming from home so allowed, we hit here// and now allow anyone to switch again).mService.mAppSwitchesAllowedTime = 0;} else {mService.mDidAppSwitch = true;}mService.doPendingActivityLaunchesLocked(false);}err = startActivityUncheckedLocked(r, sourceRecord,startFlags, true, options);

startActivityUncheckedLocked根据不同的启动模式,会有不同的逻辑处理。 标准模式最终执行逻辑如下:

if (newTask) {EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);}logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);startActivityLocked(r, newTask, doResume, keepCurTransition, options);return ActivityManager.START_SUCCESS;

startActivityLocked方法更新了历史栈,

private final void startActivityLocked(ActivityRecord r, boolean newTask,boolean doResume, boolean keepCurTransition, Bundle options) {final int NH = mHistory.size();int addPos = -1;if (!newTask) {// If starting in an existing task, find where that is...boolean startIt = true;for (int i = NH-1; i >= 0; i--) {ActivityRecord p = mHistory.get(i);if (p.finishing) {continue;}if (p.task == r.task) {// Here it is! Now, if this is not yet visible to the// user, then just add it without starting; it will// get started when the user navigates back to it.addPos = i+1;if (!startIt) {if (DEBUG_ADD_REMOVE) {RuntimeException here = new RuntimeException("here");here.fillInStackTrace();Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,here);}mHistory.add(addPos, r);r.putInHistory();mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,r.info.screenOrientation, r.fullscreen,(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);if (VALIDATE_TOKENS) {validateAppTokensLocked();}ActivityOptions.abort(options);return;}break;}if (p.fullscreen) {startIt = false;}}}// Place a new activity at top of stack, so it is next to interact// with the user.if (addPos < 0) {addPos = NH;}// If we are not placing the new activity frontmost, we do not want// to deliver the onUserLeaving callback to the actual frontmost// activityif (addPos < NH) {mUserLeaving = false;if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");}// Slot the activity into the history stack and proceedif (DEBUG_ADD_REMOVE) {RuntimeException here = new RuntimeException("here");here.fillInStackTrace();Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here);}mHistory.add(addPos, r);r.putInHistory();r.frontOfTask = newTask;if (NH > 0) {// We want to show the starting preview window if we are// switching to a new task, or the next activity's process is// not currently running.boolean showStartingIcon = newTask;ProcessRecord proc = r.app;if (proc == null) {proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);}if (proc == null || proc.thread == null) {showStartingIcon = true;}if (DEBUG_TRANSITION) Slog.v(TAG,"Prepare open transition: starting " + r);if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {mService.mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);mNoAnimActivities.add(r);} else {mService.mWindowManager.prepareAppTransition(newTask? AppTransition.TRANSIT_TASK_OPEN: AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);mNoAnimActivities.remove(r);}r.updateOptionsLocked(options);mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);boolean doShow = true;if (newTask) {// Even though this activity is starting fresh, we still need// to reset it to make sure we apply affinities to move any// existing activities from other tasks in to it.// If the caller has requested that the target task be// reset, then do so.if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {resetTaskIfNeededLocked(r, r);doShow = topRunningNonDelayedActivityLocked(null) == r;}}if (SHOW_APP_STARTING_PREVIEW && doShow) {// Figure out if we are transitioning from another activity that is// "has the same starting icon" as the next one. This allows the// window manager to keep the previous window it had previously// created, if it still had one.ActivityRecord prev = mResumedActivity;if (prev != null) {// We don't want to reuse the previous starting preview if:// (1) The current activity is in a different task.if (prev.task != r.task) prev = null;// (2) The current activity is already displayed.else if (prev.nowVisible) prev = null;}mService.mWindowManager.setAppStartingWindow(r.appToken, r.packageName, r.theme,patibilityInfoForPackageLocked(r.info.applicationInfo), r.nonLocalizedLabel,r.labelRes, r.icon, r.windowFlags,prev != null ? prev.appToken : null, showStartingIcon);}} else {// If this is the first activity, don't do any fancy animations,// because there is nothing for it to animate on top of.mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,r.info.screenOrientation, r.fullscreen,(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);ActivityOptions.abort(options);}if (VALIDATE_TOKENS) {validateAppTokensLocked();}if (doResume) {resumeTopActivityLocked(null);}}

如果要启动的Activity的组件的next等于被激活的Activity,并且状态等于Rsumed,那么直接返回,因为说明要启动的Activity已经成功激活。 如果系统当前正在终止一个Activity组件,那么就要等到终止完成之后,再启动Activity组件next,直接返回。 接下来调用startPausingLocked通知原来的Activity进入Paused状态,将焦点交给要启动的Acitivity

// We need to start pausing the current activity so the top one// can be resumed...if (mResumedActivity != null) {if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");// At this point we want to put the upcoming activity's process// at the top of the LRU list, since we know we will be needing it// very soon and it would be a waste to let it get killed if it// happens to be sitting towards the end.if (next.app != null && next.app.thread != null) {// No reason to do full oom adj update here; we'll let that// happen whenever it needs to later.mService.updateLruProcessLocked(next.app, false);}startPausingLocked(userLeaving, false);return true;}

if (prev.app != null && prev.app.thread != null) {if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);try {EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,prev.userId, System.identityHashCode(prev),prev.shortComponentName);prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,userLeaving, prev.configChangeFlags);if (mMainStack) {mService.updateUsageStats(prev, false);}} catch (Exception e) {// Ignore exception, if process died other code will cleanup.Slog.w(TAG, "Exception thrown during pause", e);mPausingActivity = null;mLastPausedActivity = null;}} else {mPausingActivity = null;mLastPausedActivity = null;}

schedulePauseActivity的具体实现在ApplicationThreadProxy类中

public final void schedulePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges) throws RemoteException {Parcel data = Parcel.obtain();data.writeInterfaceToken(IApplicationThread.descriptor);data.writeStrongBinder(token);data.writeInt(finished ? 1 : 0);data.writeInt(userLeaving ? 1 :0);data.writeInt(configChanges);mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,IBinder.FLAG_ONEWAY);data.recycle();}

通过内部的binder代理对象向应用所在进程发送一个类型为SCHEDULE_PAUSE_ACTIVITY_TRANSACTION的请求。调用ApplicaionThread的schedulePauseActivity方法

public final void schedulePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges) {queueOrSendMessage(finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,token,(userLeaving ? 1 : 0),configChanges);}

此时的finished为false,userLeaving为true,

private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {synchronized (this) {if (DEBUG_MESSAGES) Slog.v(TAG, "SCHEDULE " + what + " " + mH.codeToString(what)+ ": " + arg1 + " / " + obj);Message msg = Message.obtain();msg.what = what;msg.obj = obj;msg.arg1 = arg1;msg.arg2 = arg2;mH.sendMessage(msg);}}

handler收到PAUSE_ACTIVITY之后执行了handlePauseActivity方法

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;

private void handlePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges) {ActivityClientRecord r = mActivities.get(token);if (r != null) {//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);if (userLeaving) {performUserLeavingActivity(r);}r.activity.mConfigChangeFlags |= configChanges;performPauseActivity(token, finished, r.isPreHoneycomb());// Make sure any pending writes are now committed.if (r.isPreHoneycomb()) {QueuedWork.waitToFinish();}// Tell the activity manager we have paused.try {ActivityManagerNative.getDefault().activityPaused(token);} catch (RemoteException ex) {}}}

先说performPauseActivity再说activityPaused

final Bundle performPauseActivity(IBinder token, boolean finished,boolean saveState) {ActivityClientRecord r = mActivities.get(token);return r != null ? performPauseActivity(r, finished, saveState) : null;}

try {// Next have the activity save its current state and managed dialogs...if (!r.activity.mFinished && saveState) {state = new Bundle();state.setAllowFds(false);mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);r.state = state;}// Now we are idle.r.activity.mCalled = false;mInstrumentation.callActivityOnPause(r.activity);EventLog.writeEvent(LOG_ON_PAUSE_CALLED, UserHandle.myUserId(),r.activity.getComponentName().getClassName());if (!r.activity.mCalled) {throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() +" did not call through to super.onPause()");}} catch (SuperNotCalledException e) {throw e;}

public void callActivityOnPause(Activity activity) {activity.performPause();}

final void performPause() {mFragments.dispatchPause();mCalled = false;onPause();mResumed = false;if (!mCalled && getApplicationInfo().targetSdkVersion>= android.os.Build.VERSION_CODES.GINGERBREAD) {throw new SuperNotCalledException("Activity " + mComponent.toShortString() +" did not call through to super.onPause()");}mResumed = false;}

protected void onPause() {if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);getApplication().dispatchActivityPaused(this);mCalled = true;}

/* package */ void dispatchActivityPaused(Activity activity) {Object[] callbacks = collectActivityLifecycleCallbacks();if (callbacks != null) {for (int i=0; i<callbacks.length; i++) {((ActivityLifecycleCallbacks)callbacks[i]).onActivityPaused(activity);}}

到这里,前一个Activiy进入了onActivityPaused状态。 ActivityManagerProxy的activityPaused方法

public void activityPaused(IBinder token) throws RemoteException{Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IActivityManager.descriptor);data.writeStrongBinder(token);mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);reply.readException();data.recycle();reply.recycle();}

通过binder对象向ActivityManagerService发送了类型为ACTIVITY_PAUSED_TRANSACTION的进程通信请求。

public final void activityPaused(IBinder token) {final long origId = Binder.clearCallingIdentity();mMainStack.activityPaused(token, false);Binder.restoreCallingIdentity(origId);}

又到了ActivityStack中

final void activityPaused(IBinder token, boolean timeout) {if (DEBUG_PAUSE) Slog.v(TAG, "Activity paused: token=" + token + ", timeout=" + timeout);ActivityRecord r = null;synchronized (mService) {int index = indexOfTokenLocked(token);if (index >= 0) {r = mHistory.get(index);mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);if (mPausingActivity == r) {if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r+ (timeout ? " (due to timeout)" : " (pause complete)"));r.state = ActivityState.PAUSED;completePauseLocked();} else {EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,r.userId, System.identityHashCode(r), r.shortComponentName,mPausingActivity != null? mPausingActivity.shortComponentName : "(none)");}}}}

然后通过resumeTopActivityLocked启动栈顶的Activity

{// Whoops, need to restart this activity!if (!next.hasBeenLaunched) {next.hasBeenLaunched = true;} else {if (SHOW_APP_STARTING_PREVIEW) {mService.mWindowManager.setAppStartingWindow(next.appToken, next.packageName, next.theme,patibilityInfoForPackageLocked(next.info.applicationInfo),next.nonLocalizedLabel,next.labelRes, next.icon, next.windowFlags,null, true);}if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);}startSpecificActivityLocked(next, true, true);}

startSpecificActivityLocked首先会以用户ID和进程名来检查系统中是否存在一个对应的应用程序,如果存在,会直接通知这个应用程序进程将该Acitivy启动起来,否则会先创建对应的应用进程,然后再启动Activity组件

private final void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {// Is this activity's application already running?ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid);if (r.launchTime == 0) {r.launchTime = SystemClock.uptimeMillis();if (mInitialStartTime == 0) {mInitialStartTime = r.launchTime;}} else if (mInitialStartTime == 0) {mInitialStartTime = SystemClock.uptimeMillis();}if (app != null && app.thread != null) {try {app.addPackage(r.info.packageName);realStartActivityLocked(r, app, andResume, checkConfig);return;} catch (RemoteException e) {Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e);}// If a dead object exception was thrown -- fall through to// restart the application.}mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false);}

进程创建过程

startProcessLocked方法先获取要创建应用程序的进程用户ID和用户组ID,然后调用Progress类的静态函数创建新的进程。

Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",app.processName, uid, uid, gids, debugFlags, mountExternal,app.info.targetSdkVersion, app.info.seinfo, null);BatteryStatsImpl bs = app.batteryStats.getBatteryStats();synchronized (bs) {if (bs.isOnBattery()) {app.batteryStats.incStartsLocked();}}

ActivityThread中创建进程

public static void main(String[] args) {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());Security.addProvider(new AndroidKeyStoreProvider());Process.setArgV0("<pre-initialized>");Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();thread.attach(false);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}AsyncTask.init();if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}}

进程创建过程中,首先调用Looper的PrepareMainLooper来创建主线程中的消息循环,然后创建了ActivityThread对象,调用attach方法,向ActivityManager发送启动完成通知,最后启动主线程中的消息循环。

ActivityThread的attach方法最终通过binder方式调用ActivityManagerService的attachApplication方法

private void attach(boolean system) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {ViewRootImpl.addFirstDrawHandler(new Runnable() {public void run() {ensureJitEnabled();}});android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",UserHandle.myUserId());RuntimeInit.setApplicationObject(mAppThread.asBinder());IActivityManager mgr = ActivityManagerNative.getDefault();try {mgr.attachApplication(mAppThread);} catch (RemoteException ex) {// Ignore}}

public final void attachApplication(IApplicationThread thread) {synchronized (this) {int callingPid = Binder.getCallingPid();final long origId = Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid);Binder.restoreCallingIdentity(origId);}}

调用attachApplicationLocked之后,进程相关信息创建并且关联完毕。

realStartActivityLocked

回到ActivityStack类中,调用realStartActivityLocked方法来启动Activity组件。

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,System.identityHashCode(r), r.info,new Configuration(mService.mConfiguration),pat, r.icicle, results, newIntents, !andResume,mService.isNextTransitionForward(), profileFile, profileFd,profileAutoStop);

通过Binder,最终调用了ActivityThread的scheduleLaunchActivity方法,

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,Bundle state, List<ResultInfo> pendingResults,List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {ActivityClientRecord r = new ActivityClientRecord();r.token = token;r.ident = ident;r.intent = intent;r.activityInfo = info;patInfo = 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);}

private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {synchronized (this) {if (DEBUG_MESSAGES) Slog.v(TAG, "SCHEDULE " + what + " " + mH.codeToString(what)+ ": " + arg1 + " / " + obj);Message msg = Message.obtain();msg.what = what;msg.obj = obj;msg.arg1 = arg1;msg.arg2 = arg2;mH.sendMessage(msg);}}

case LAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");ActivityClientRecord r = (ActivityClientRecord)msg.obj;r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, patInfo);handleLaunchActivity(r, null);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);} break;

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);Activity a = performLaunchActivity(r, customIntent);if (a != null) {r.createdConfig = new Configuration(mConfiguration);Bundle oldState = r.state;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;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}}}

组件启动过程是在performLaunchActivity这个方法中

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;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;}

callActivityOnCreate这个方法会调用要启动的Acitivy的onCreate方法。

细节太多,主要算是熟悉流程。源码跟别人的讲解结合着看,感觉更好理解些。单纯的看源码有点蒙,单纯的看源码分析的书很快就会淡忘。底层的一些东西还是需要了解一些的。

欢迎扫描二维码,关注公众号

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。