Activity啟動流程原始碼解析上(8.0)
上個小節我們學習了跨程序通訊,相信大家對於AIDL已經很熟悉了,今天我們趁熱打鐵,一起來看下Activity的啟動流程。對AIDL還不瞭解的小夥伴請先移步至上小節文章:ofollow,noindex">https://www.jianshu.com/p/1f1472991d72 。
我們知道,Activity有兩種常見的啟動方式,一種是在桌面點選應用圖示,進入應用程式的主介面,另一種方式就是使用者在應用程式的Activity點選某個按鈕或者其他跳轉到另一個Activity。我先簡單說下Android系統的啟動順序:init程序 -> Zygote程序 -> SystemServer程序 -> 應用程式程序。我們大家都知道,Android系統是基於Linux核心的,所以首先啟動Linux的init程序,接著由init程序啟動Zygote(受精卵)程序。Zygote程序可以說是所有Android程序的父程序,後續啟動的SystemServer程序和各種應用程式程序都是由Zygote程序fork出來的。而我們的手機桌面就是Android系統啟動的第一個應用程式程序,上述兩種Activity的啟動方式底層都是通過IPC機制來實現的。
我先舉個栗子來考考大家,當我們在應用程式中由ActivityA跳轉到ActivityB,兩者的生命週期方法執行的順序是怎樣的呢?答案是:ActivityA onPause -> ActivityB onCreate -> ActivityB onStart -> ActivityB onResume -> ActivityA onStop。這個也是面試官經常問的一個小知識點,如果你答錯的話可要好好補習下基礎知識啦哈哈哈,在這裡我們就以兩者的生命週期方法執行順序為引線,來從原始碼的角度看下Activity的啟動流程。
下面的程式碼我們再熟悉不過了:
Intent intent = new Intent(MainActivity.this,OtherActivity.class); startActivity(intent);
跟進去startActivity方法看下:
#Activity @Override public void startActivity(Intent intent) { this.startActivity(intent, null); } -- > @Override public void startActivity(Intent intent, @Nullable 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(@RequiresPermission Intent intent, int requestCode) { startActivityForResult(intent, requestCode, null); } --> public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { options = transferSpringboardActivityOptions(options); // 重點 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) { mStartedActivity = true; } cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { mParent.startActivityFromChild(this, intent, requestCode); } } }
可以看到方法最終會呼叫到mInstrumentation.execStartActivity方法,我們接著跟:
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; Uri referrer = target != null ? target.onProvideReferrer() : null; if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } try { intent.migrateExtraStreamToClipData(); intent.prepareToLeaveProcess(who); // 重點 int result = ActivityManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }
上述程式碼有刪減,我們可以看到方法中呼叫到 ActivityManager.getService().startActivity方法。ActivityManager.getService()方法獲取到的是什麼呢?我們跟進去看下:
# ActivityManager public static IActivityManager getService() { return IActivityManagerSingleton.get(); }
接著看下IActivityManagerSingleton的定義:
private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } };
IActivityManagerSingleton的get方法直接將am返回出去了,am又是什麼呢?可以看到am是通過IActivityManager.Stub.asInterface(b); 獲取到的,am所屬型別為 IActivityManager 。看到這裡大家有沒有一種似曾相識的感覺?AIDL,對的!我們的應用程式就屬於客戶端程序,而SystemServer程序則是服務端程序,在IActivityManager 介面中定義了我們應用程式程序到SystemServer程序單向通訊需要呼叫的各種方法。SystemServer程序中對應的Binder實現類就是ActivityManagerService(簡稱AMS),AMS中的方法都是執行在服務端的Binder執行緒池中。SystemServer程序到我們的應用程序單向通訊的介面為IApplicationThread,對應的Binder實現類為ApplicationThread,大家翻看原始碼就可以發現,ApplicationThread是ActivityThread的內部類,同樣ApplicationThread類中的方法都是執行在客戶端的Binder執行緒池中,正因為如此,所以我們收到服務端程序的指令後需要藉助Handler,也就是mH(Handler)切換到UI執行緒進行處理。
我們回過頭接著看,程式碼中呼叫ActivityManager.getService().startActivity方法,也就是呼叫到AMS的startActivity方法,我們跟進去ActivityManagerService這個類去看下:
@Override public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId()); }
可以看到方法中直接呼叫了startActivityAsUser方法,我們接著跟下去,接下來的程式碼量有點多,做好準備哈哈。
#ActivityManagerService @Override public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) { enforceNotIsolatedCaller("startActivity"); userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); // TODO: Switch to user app stacks here. return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, null, null, bOptions, false, userId, null, null, "startActivityAsUser"); } --> #ActivityStarter//程式碼適當刪減 final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, WaitResult outResult, Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask, String reason) { final ActivityRecord[] outRecord = new ActivityRecord[1]; //重點 int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, container, inTask, reason); Binder.restoreCallingIdentity(origId); } --> #ActivityStarter int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask, String reason) { if (TextUtils.isEmpty(reason)) { throw new IllegalArgumentException("Need to specify a reason."); } mLastStartReason = reason; mLastStartActivityTimeMs = System.currentTimeMillis(); mLastStartActivityRecord[0] = null; //重點 mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord, container, inTask); if (outActivity != null) { // mLastStartActivityRecord[0] is set in the call to startActivity above. outActivity[0] = mLastStartActivityRecord[0]; } return mLastStartActivityResult; } --> #ActivityStarter /** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */ private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent, String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int realCallingPid, int realCallingUid, int startFlags, ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container, TaskRecord inTask) { //重點 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask, outActivity); } --> #ActivityStarter private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { int result = START_CANCELED; try { mService.mWindowManager.deferSurfaceLayout(); //重點 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, outActivity); } finally { // If we are not able to proceed, disassociate the activity from the task. Leaving an // activity in an incomplete state can lead to issues, such as performing operations // without a window container. if (!ActivityManager.isStartResultSuccessful(result) && mStartActivity.getTask() != null) { mStartActivity.getTask().removeActivity(mStartActivity); } mService.mWindowManager.continueSurfaceLayout(); } postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,mSourceRecord, mTargetStack); return result; } --> #ActivityStarter // Note: This method should only be called from {@link startActivity}. private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { //重點 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); }
好吧,終於呼叫到ActivityStackSupervisor類了,我們接著跟:
#ActivityStackSupervisor boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (targetStack != null && isFocusedStack(targetStack)) { return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } final ActivityRecord r = mFocusedStack.topRunningActivityLocked(); if (r == null || r.state != RESUMED) { //重點在這裡r可以理解為將要執行onPause方法的上一個Activity mFocusedStack.resumeTopActivityUncheckedLocked(null, null); } else if (r.state == RESUMED) { // Kick off any lingering app transitions form the MoveTaskToFront operation. mFocusedStack.executeAppTransition(targetOptions); } return false; } --> #ActivityStack boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { if (mStackSupervisor.inResumeTopActivity) { // Don't even start recursing. return false; } boolean result = false; try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; // 重點 result = resumeTopActivityInnerLocked(prev, options); } finally { mStackSupervisor.inResumeTopActivity = false; } return result; } --> #ActivityStack private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { if (mResumedActivity != null) { //重點 mResumedActivity 指的就是將要執行onPause方法的上一個Activity,這裡可以說是onPause方法執行的入口 pausing |= startPausingLocked(userLeaving, false, next, false); } }
我跟跟跟:
#ActivityStack /** * Start pausing the currently resumed activity.It is an error to call this if there * is already an activity being paused or there is no resumed activity * @return Returns true if an activity now is in the PAUSING state, and we are waiting for * it to tell us when it is done. */ final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, boolean pauseImmediately) { ActivityRecord prev = mResumedActivity; mResumedActivity = null; try { EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY, prev.userId, System.identityHashCode(prev), prev.shortComponentName); mService.updateUsageStats(prev, false); prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, userLeaving, prev.configChangeFlags, pauseImmediately); } catch (Exception e) { // Ignore exception, if process died other code will cleanup. Slog.w(TAG, "Exception thrown during pause", e); mPausingActivity = null; mLastPausedActivity = null; mLastNoHistoryActivity = null; }
我們先看下註解,大概意思就是說這個方法是用來執行上個Activity的onPause方法的,如果上個Activity在此之前已經為paused狀態的話,呼叫這個方法會出錯。在呼叫到try程式碼塊中的prev.app.thread.schedulePauseActivity方法後,會直接return true,然後等待客戶端程序告訴我們結果。然後在resumeTopActivityInnerLocked方法中由於startPausingLocked方法的返回值為true,會使得pausing 的值為true,後續進入一個if語句直接return掉了,程式碼不會繼續向下執行。至於呼叫到try程式碼塊中的prev.app.thread.schedulePauseActivity方法後,為什麼會直接return true,大家看下程式碼細節就會明白了,這裡就不過細分析了。在上述方法中有一個重要的點需要我們注意下,那就是try程式碼塊執行前的上述兩行程式碼,可以看到,程式碼中首先將mResumedActivity賦值給prev,接著將 mResumedActivity 置為null。為什麼要這麼操作呢?答案就是後續的IPC過程中會再次呼叫到ActivityStack類的resumeTopActivityInnerLocked方法,這個時候由於mResumedActivity已經為null,程式不會進入到if語句塊再次執行startPausingLocked方法,而是會接著向下執行。
我們可以看到,在上述程式碼中,最終會呼叫到prev.app.thread.schedulePauseActivity方法,也就是呼叫到客戶端程序ApplicationThread類的schedulePauseActivity方法。不知道大家在這裡有沒有想過,我們的應用程式客戶端程序是怎麼將ApplicationThread註冊到SystemServer程序的呢?答案當然是在我們的應用程式客戶端程序啟動的時候啦,怎麼你不信?我們上程式碼哈哈:
我們都知道,我們的應用程式程序啟動的起點就是它的ActivityThread類的main方法,下面我們一起來看下(程式碼有刪減):
public static void main(String[] args) { // 1. Looper.prepareMainLooper(); // 2. ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // 3. Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
我們可以看到,程式碼中首先呼叫了 Looper.prepareMainLooper();接著建立了一個當前ActivityThread 類的例項物件,呼叫它的attach方法,最後呼叫到Looper.loop();方法進行迴圈。重點就在這個attach方法,我們跟進去看下:
private void attach(boolean system) { final IActivityManager mgr = ActivityManager.getService(); try { // 重點 mgr.attachApplication(mAppThread); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } }
上述程式碼有所刪減,我們可以看到attach方法中最終會呼叫到 mgr.attachApplication方法,將mAppThread作為引數,傳遞過去,mAppThread是什麼呢?我們看下:
final ApplicationThread mAppThread = new ApplicationThread();
哈哈,可以看到mAppThread 就是ApplicationThread 類的一個例項物件,也就是說attach方法中呼叫到mgr.attachApplication方法,將ApplicationThread 類的例項物件mAppThread 作為引數傳遞過去。通過mgr的定義我們可以知道,這是從客戶端程序到SystemServer程序的一次IPC,所以最終會呼叫到AMS的attachApplication方法,我們跟過去看下:
@Override public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); //重點 attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); } } --> private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { 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.forcingToImportant = null; updateProcessForegroundLocked(app, false, false); app.hasShownUi = false; app.debugging = false; app.cached = false; app.killedByAm = false; app.killed = false;
可以看到attachApplicationLocked方法中呼叫到app.makeActive方法(app型別為ProcessRecord),將我們ApplicationThread 類的例項物件作為第一個引數傳遞了過去,我們跟進去makeActive方法看下:
public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) { if (thread == null) { final ProcessState origBase = baseProcessTracker; if (origBase != null) { origBase.setState(ProcessStats.STATE_NOTHING, tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList); origBase.makeInactive(); } baseProcessTracker = tracker.getProcessStateLocked(info.packageName, uid, info.versionCode, processName); baseProcessTracker.makeActive(); for (int i=0; i<pkgList.size(); i++) { ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); if (holder.state != null && holder.state != origBase) { holder.state.makeInactive(); } holder.state = tracker.getProcessStateLocked(pkgList.keyAt(i), uid, info.versionCode, processName); if (holder.state != baseProcessTracker) { holder.state.makeActive(); } } } thread = _thread; }
可以看到在makeActive方法的最後,將我們ApplicationThread 類的例項物件賦值給app(ProcessRecord型別)的成員變數thread ,這樣就完成了註冊。
好了,我們回過頭接著看,在上述startPausingLocked方法中,最終呼叫到prev.app.thread.schedulePauseActivity方法,也就是呼叫到客戶端程序ApplicationThread類的schedulePauseActivity方法,我們跟過去看下:
public final void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) { int seq = getLifecycleSeq(); if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this + " operation received seq: " + seq); sendMessage( finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, token, (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0), configChanges, seq); }
可以看到客戶端程序ApplicationThread類的schedulePauseActivity方法中直接呼叫了sendMessage方法,接著跟:
private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) { if (DEBUG_MESSAGES) Slog.v( TAG, "SCHEDULE " + mH.codeToString(what) + " arg1=" + arg1 + " arg2=" + arg2 + "seq= " + seq); Message msg = Message.obtain(); msg.what = what; SomeArgs args = SomeArgs.obtain(); args.arg1 = obj; args.argi1 = arg1; args.argi2 = arg2; args.argi3 = seq; msg.obj = args; mH.sendMessage(msg); }
可以看到sendMessage方法中直接呼叫mH(Handler)的sendMessage方法傳送了一條訊息,大家想下,這裡為什麼需要藉助Handler來發送一條訊息呢?答案就是ApplicationThread類的schedulePauseActivity方法是執行在客戶端程序的Binder執行緒池中,需要切換至UI執行緒,肯定要藉助偉大的Handler啦。下面我們到mH的handleMessage方法中看下:
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; 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"); SomeArgs args = (SomeArgs) msg.obj; handlePauseActivity((IBinder) args.arg1, false, (args.argi1 & USER_LEAVING) != 0, args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3); maybeSnapshot(); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; case PAUSE_ACTIVITY_FINISHING: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause"); SomeArgs args = (SomeArgs) msg.obj; handlePauseActivity((IBinder) args.arg1, true, (args.argi1 & USER_LEAVING) != 0, args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; case STOP_ACTIVITY_SHOW: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop"); SomeArgs args = (SomeArgs) msg.obj; handleStopActivity((IBinder) args.arg1, true, args.argi2, args.argi3); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; case STOP_ACTIVITY_HIDE: { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop"); SomeArgs args = (SomeArgs) msg.obj; handleStopActivity((IBinder) args.arg1, false, args.argi2, args.argi3); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); } break; ......
可以看到在 case PAUSE_ACTIVITY 語句段呼叫了handlePauseActivity方法,這個就是用來執行上個Activity的onPause方法的入口,我們跟進去:
private void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport, int seq) { ActivityClientRecord r = mActivities.get(token); //1. performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity"); if (!dontReport) { try { //2. ActivityManager.getService().activityPaused(token); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } mSomeActivitiesChanged = true; } }
在這裡我們先來看下標註 1 處,呼叫到performPauseActivity方法,還等什麼,肯定跟進去啊哈哈:
final Bundle performPauseActivity(IBinder token, boolean finished, boolean saveState, String reason) { ActivityClientRecord r = mActivities.get(token); return r != null ? performPauseActivity(r, finished, saveState, reason) : null; } --> final Bundle performPauseActivity(ActivityClientRecord r, boolean finished, boolean saveState, String reason) { if (!r.activity.mFinished && saveState) { //1. callCallActivityOnSaveInstanceState(r); } //2. performPauseActivityIfNeeded(r, reason); }
標註 1 處的方法最終會回撥Activity的onSaveInstanceState方法,我們一般情況下會重寫onSaveInstanceState方法來進行儲存資料,大家感興趣的可以點開原始碼看下,這裡就不展開分析了,我們一起來看下 2 處的performPauseActivityIfNeeded方法,跟進去:
private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) { try { r.activity.mCalled = false; //重點跟進去 mInstrumentation.callActivityOnPause(r.activity); } } catch (SuperNotCalledException e) { throw e; } } --> #Instrumentation public void callActivityOnPause(Activity activity) { activity.performPause(); } --> #Activity final void performPause() { mDoReportFullyDrawn = false; 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; }
最終終於在performPause方法中找到Activity的onPause方法回調了!容老夫大笑兩分鐘先哈哈哈。
好了,讓我們回到handlePauseActivity方法接著看下 2 處程式碼,可以看到 2 處呼叫到ActivityManager.getService().activityPaused方法,這是一次由客戶端程序向SystemServer程序發起的單向IPC,最終會呼叫到AMS的activityPaused方法。
欲知後事如何,請看下回分解,時間不早了,我要先洗洗睡了,明早還要早起上班。