Android Activity生命周期是如何實現的

本文是 Android 系統學習系列文章中的第三章節的內容,在前面的文章 Android 應用進程啟動流程 講了 Android 是如何啟動的,在這篇文章里,將詳細說明 Activity 生命周期的實現原理,onCreate、onResume、onPause 等主要生命周期回調是如何實現的,ActivityManangerService 在里面扮演的角色。對此系列感興趣的同學,可以收藏這個鏈接 Android 系統學習,也可以點擊 http://www.woaitqs.cc/feed.xml 進行訂閱。


背景知識介紹

這篇文章中涉及到 Binder 的設計實現,如果對這一塊不是很熟悉的話,建議閱讀后續代碼時,先看看下面的鏈接的內容,特別是 AIDL 的實現。

  • ActivityThread: 運行在應用進程的主線程上,響應 ActivityManangerService 啟動、暫停Activity,廣播接收等消息。
  • ActivityThread.mH: 繼承自 Handler,用于發送組件相關的事件消息。
  • ActivityThread.ApplicationThread: Binder 對象, 通過 ApplicationThreadProxy 的構造函數注入進去,作為 ActivityThread 的內部類,響應具體的 ActivityManagerService 的方法請求。
  • ApplicationThreadProxy: Binder Proxy 對象,傳遞到 ActivityManagerService 中,當 ActivityManagerService 需要讓 Activity 做相應諸如啟動、銷毀等事情時,會通過 ActivityThread.ApplicationThread 執行具體的業務邏輯。
  • Instrumentation: Android 提供的用于監聽 Activity 與系統交互的機制。
  • ActivityManagerService: Android 核心的組件服務,用于管理控制各類組件。
From Activity 和 To Activity

從實際的例子出發,會更方便理解,這里以從列表頁面(以下簡稱 From Activity)跳轉到詳情頁面(以下簡稱 To Activity)為例,說明在這個過程中發生的事情。


Activity 生命周期實現

1)From Activity 請求 ActivityManageService 啟動 To Activity

首先當點擊 From Activity 中的列表頁時,通過下面的代碼發送 Intent,啟動 To Activity。

Intent intent = new Intent(context, Detail.class);
intent.putInt(Const.REST_ID, id);
startActivity(intent);

這段代碼會執行到 Activity 的 startActivity 方法,Activity 中也有多個不同簽名的 startActivity,都會執行到 startActivityForResult 這個方法,扼要的代碼如下:

public void startActivityForResult(Intent intent, int requestCode, @Nullable 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());
      }
      // ...
      cancelInputsAndStartExitTransition(options);
  } 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);
      }
  }
}

無論 Parent 是否為空,最后都是通過 Instrumentation 來執行啟動的任務,Instrumentation 是 Android 設計者提供出來的中間層,方便開發者監聽系統各種與 Application 的交互,同時也對測試工作很有幫助,接下來看看 Instrumentation 的具體代碼。

Instrumentation 在提供相應的監聽邏輯后,調用了 ActivityManagerNative 來執行相應的邏輯,如下所示。

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    ...
    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, , null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

這里先看看 getDefault 的實現,看看里面返回的是什么?

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        IBinder b = ServiceManager.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        IActivityManager am = asInterface(b);
        if (false) {
            Log.v("ActivityManager", "default service = " + am);
        }
        return am;
    }
};

這里看到返回的是 ServiceManager.getService,ServiceManager 在 Framework 充當了 DNS 的作用,通過 ServiceManager 可以找到其他的系統服務,這里返回的正是名為的 activity 的 服務。在前面提供的鏈接 Android Binder 完全解析(三)AIDL實現原理分析 中,也講到了 ServiceManager 的實現,會更詳細些。

接下來看看 asInterface 的實現,這不正是很標準的 AIDL 實現嗎?傳入的 obj 對象正是鼎鼎大名的 ActivityManageService, 這里通過 ActivityManagerProxy 進行代理,將接口暴露到應用層,這樣對于調用出于 System_server 進程的方法時,就如同在本地調用一樣。

static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    IActivityManager in =
        (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }

    return new ActivityManagerProxy(obj);
}

在 ActivityManagerProxy 中對 startActivity 進行轉發的代碼如下所示:

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
      Parcel data = Parcel.obtain();
      Parcel reply = Parcel.obtain();
      data.writeInterfaceToken(IActivityManager.descriptor);
      data.writeStrongBinder(caller != null ? caller.asBinder() : null);
      data.writeString(callingPackage);
      intent.writeToParcel(data, 0);
      data.writeString(resolvedType);
      data.writeStrongBinder(resultTo);
      data.writeString(resultWho);
      data.writeInt(requestCode);
      data.writeInt(startFlags);
      if (profilerInfo != null) {
          data.writeInt(1);
          profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
      } else {
          data.writeInt(0);
      }
      if (options != null) {
          data.writeInt(1);
          options.writeToParcel(data, 0);
      } else {
          data.writeInt(0);
      }
      mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
      reply.readException();
      int result = reply.readInt();
      reply.recycle();
      data.recycle();
      return result;
  }

這里采用的方式正是 Binder 的調用方式,在 ActivityManagerProxy 中持有了 ActivityManagerService 提供的 Binder 接口,所有的命令都是通過這個 Binder 進行消息發送的,在客戶端進程調用 startActivity 時,會調用到 ActivityManagerService 的 startActivity 方法里面,在進行一些列的處理后,會執行到 ActivityStackSupervisor 的 startActivityMayWait 方法里面,繼而調用到 startActivityLocked 方法中。

至此為止,在 From Activity 的啟動 Activity 請求,已經傳遞到 ActivityManagerService 中。

2)ActivityManagerService 響應啟動請求

首先調用到 startActivity 方法里面。

@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle options) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
        resultWho, requestCode, startFlags, profilerInfo, options,
        UserHandle.getCallingUserId());
}

其后進入到 startActivityAsUser 方法里面,在這個方法中,將邏輯移交到 ActivityStackSupervisor 中去。

@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
    enforceNotIsolatedCaller("startActivity");
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
            false, ALLOW_FULL_ONLY, "startActivity", null);
    // TODO: Switch to user app stacks here.
    return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, options, false, userId, null, null);
}

這里的 mStackSupervisor 就是 ActivityStackSupervisor , 這個類在 Android 4.4 以后才引入的,用于管理 ActivityStack。對于前面舉得這個例子,方法的運行 Trace 會沿著下面的方法來執行。

ActivityManagerService.startActivity()
ActvityiManagerService.startActivityAsUser()
ActivityStackSupervisor.startActivityMayWait()
ActivityStackSupervisor.startActivityLocked()
ActivityStackSupervisor.startActivityUncheckedLocked()
ActivityStackSupervisor.startActivityLocked()
ActivityStackSupervisor.resumeTopActivitiesLocked()
ActivityStackSupervisor.resumeTopActivityInnerLocked()

里面的邏輯非常復雜,也不在今天主要講的范圍內,這里只做簡單介紹。

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 config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
            ...
            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);
            ...
            return res;
    }

在 startActivityMayWait 中,會去查看是否存在相應的Activity,如果同時存在多個相應的 Activity,彈出一個對話框,讓用戶進行選擇。

final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage,
            int realCallingPid, int realCallingUid, int startFlags, Bundle options,
            boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
            ActivityContainer container, TaskRecord inTask) {
        int err = ActivityManager.START_SUCCESS;
        ...
        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);
        ...
        return err;
    }

在 startActivityLocked 和 startActivityUncheckedLocked 方法里, 建立了相應的 ActivityRecord 對象,加入到 TaskRecord 中,并根據相應的 LaunchMode 和 Flag 進行相應的進棧出棧處理,所有的細節都在這兩個方法里面,就不在展開了。關于 Activity 的棧,這里有一篇很好的文章,可供翻閱,Understand Android Activity's launchMode: standard, singleTop, singleTask and singleInstance,還有一個不錯的 PPT,講解關于 LaunchMode 中的一些坑,Manipulating Android tasks and back stack

最后執行到 startActivityLocked,調用 resumeTopActivitiesLocked 方法。

final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
        // ...
        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

經過一些方法的參數處理后,執行 resume 代碼邏輯,在 resumeTopActivityInnerLocked 方法里。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
        ...
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
        }        ...
        return true;
    }

在啟動下一個 Activity,需要將上一個 Activity 暫停掉,這在面試中也經常問到,大家可以注意下。上面的代碼也也驗證了先行 pause 的邏輯,在下面的章節中看看是如何暫停 From Activity的。

3)暫停 From Activity

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
            boolean dontWait) {
        ...
        if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            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, dontWait);
            } 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;
            }
        } else {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }
        ...
    }

startPausingLocked 的方法里面調用了 prev.app.thread.schedulePauseActivity 這個方法,其中這里的 thread,是上文中傳遞過去的 IApplicationThread,這里指的是 ApplicationThreadProxy 對象。這里和前面調用 ActivityManageService 的方式相同,也是采用的 Binder 框架,將要具體的數據通過 Parcable 傳遞到 ActivityThread.ApplicationThread 中,接下來看看 ActivityThread 中 schedulePauseActivity的具體實現。

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

這里的 sendMessage 方法,是通過 ActivityThread 的 mH 這個類來進行 Message 的發放,這里傳遞的消息是 PAUSE_ACTIVITY_FINISHING,我們看看 ActivityThread 是如何處理這個消息的。

case PAUSE_ACTIVITY_FINISHING:
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
    handlePauseActivity((IBinder)msg.obj, true, (msg.arg1&1) != 0, msg.arg2,
            (msg.arg1&1) != 0);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    break;

邏輯還藏在 handlePauseActivity 里面,就接著往下看。

private void handlePauseActivity(IBinder token, boolean finished,
        boolean userLeaving, int configChanges, boolean dontReport) {
    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.
        if (!dontReport) {
            try {
                ActivityManagerNative.getDefault().activityPaused(token);
            } catch (RemoteException ex) {
            }
        }
        mSomeActivitiesChanged = true;
    }
}
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState) {
    // ...
    mInstrumentation.callActivityOnPause(r.activity);
    // ...
    return !r.activity.mFinished && saveState ? r.state : null;
}

又來到了 Instrumentation 這個類里面,前文也提到這個類監聽著應用與系統發生的通信,看來它還是挺盡職的。

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

這里執行的方法是 Activity.performPause,這應該就是這次 Pause 流程的終點了。

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

果然,我們熟悉的 onPause 回調就放在這里,到此 Pause 過程就完成了,現在接著回到 handlePauseActivity 里面去,還有方法沒有執行完成。

private void handlePauseActivity(IBinder token, boolean finished,
        boolean userLeaving, int configChanges, boolean dontReport) {
    ActivityClientRecord r = mActivities.get(token);
    if (r != null) {
        // ...
        if (!dontReport) {
            try {
                ActivityManagerNative.getDefault().activityPaused(token);
            } catch (RemoteException ex) {
            }
        }
        mSomeActivitiesChanged = true;
    }
}

在執行完成 Pause 過程后,繼續通過 ActivityManagerNative 執行 ActivityManagerService 的 activityPause 方法,這個機制與前面的過程相同。從這里可以看到,ActivityThread 和 ActivityManagerService 互相持有著雙方的把柄,不,是 Binder 對象,Binder 機制使得在跨進程調用的時候,和同進程的方法調用沒有什么區別。

4)啟動 To Activity

@Override
public final void activityPaused(IBinder token) {
    final long origId = Binder.clearCallingIdentity();
    synchronized(this) {
        ActivityStack stack = ActivityRecord.getStackLocked(token);
        if (stack != null) {
            stack.activityPausedLocked(token, false);
        }
    }
    Binder.restoreCallingIdentity(origId);
}

Activity 的 pause 方法,也是通過 Stack 來完成,這樣便于進行棧管理,來看看具體的實現。

final void activityPausedLocked(IBinder token, boolean timeout) {
        //...
            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
                    + (timeout ? " (due to timeout)" : " (pause complete)"));
            completePauseLocked(true);
        //...
}

private void completePauseLocked(boolean resumeNext) {
    //...
    if (resumeNext) {
        final ActivityStack topStack = mStackSupervisor.getFocusedStack();
        if (!mService.isSleepingOrShuttingDown()) {
            mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
        } else {
            mStackSupervisor.checkReadyForSleepLocked();
            ActivityRecord top = topStack.topRunningActivityLocked(null);
            if (top == null || (prev != null && top != prev)) {
                // If there are no more activities available to run,
                // do resume anyway to start something.  Also if the top
                // activity on the stack is not the just paused activity,
                // we need to go ahead and resume it to ensure we complete
                // an in-flight app switch.
                mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
            }
        }
    }
    //...
}

接下來繼續經過如下的調用棧

resumeTopActivitiesLocked
ActivityStack.resumeTopActivityLocked()
resumeTopActivityInnerLocked
startSpecificActivityLocked

最后調到了 startSpecificActivityLocked 方法里面來。

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, true);
    r.task.stack.setLaunchTime(r);
    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                // Don't add this if it is a platform component that is marked
                // to run in multiple processes, because this is actually
                // part of the framework so doesn't make sense to track as a
                // separate apk in the process.
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                        mService.mProcessStats);
            }
            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, true);
}

這個方法存在兩個分支,當對應的應用進程存在時,直接執行 realStartActivityLocked 方法,否者就先新建應用進程。關于新建應用進程的事宜,在我的這篇博客http://www.woaitqs.cc/2016/06/21/activity-service.html里面,說得相對詳細,這里就不再詳細說明了,其實在進程啟動完畢后,最后也會調用到 realStartActivityLocked 到這個方法里面來。

app.thread.scheduleLaunchActivity(new Intent(r.intent), r,  
    System.identityHashCode(r),  
    r.info, r.icicle, results, newIntents, !andResume,  
    mService.isNextTransitionForward());  

在 realStartActivityLocked 方法中,同樣也是通過 ApplicationThreadProxy 進行遠程方法調用,最后會執行到 ActivityThread 的scheduleLaunchActivity 的方法中來,在下面的代碼里面,可以看出 Binder 調用。

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
        ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,  
        List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)  
        throws RemoteException {  
    Parcel data = Parcel.obtain();  
    data.writeInterfaceToken(IApplicationThread.descriptor);  
    intent.writeToParcel(data, 0);  
    data.writeStrongBinder(token);  
    data.writeInt(ident);  
    info.writeToParcel(data, 0);  
    data.writeBundle(state);  
    data.writeTypedList(pendingResults);  
    data.writeTypedList(pendingNewIntents);  
    data.writeInt(notResumed ? 1 : 0);  
    data.writeInt(isForward ? 1 : 0);  
    mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,  
        IBinder.FLAG_ONEWAY);  
    data.recycle();  
}

和 Pause 的過程相同,只是這里發送的消息是 LAUNCH_ACTIVITY,我們看看在這一塊是如何處理的。

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);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

handleLaunchActivity 的具體實現如下:

private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {  
    //......  

    Activity a = performLaunchActivity(r, customIntent);  

    if (a != null) {  
        r.createdConfig = new Configuration(mConfiguration);  
        Bundle oldState = r.state;  
        handleResumeActivity(r.token, false, r.isForward);  

        //......  
    } else {  
        //......  
    }  
}  

這里有兩個重要的方法,分別是 performLaunchActivity 和 handleResumeActivity 方法。

先看看 performLaunchActivity 方法,這里由幾個重要的部分組成。

收集相應的組件信息。

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 是通過反射構建出的對象。

Activity activity = null;
try {
    java.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);
    }
}

如果沒有相應的 Application 信息,則會先建立相應的 Application。

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

接著把 Activity 對象,attach 到相應的運行環境上面去。

activity.attach(appContext, this, getInstrumentation(), r.token,  
r.ident, app, r.intent, r.activityInfo, title, r.parent,  
r.embeddedID, r.lastNonConfigurationInstance,  
r.lastNonConfigurationChildInstances, config);  

最后,又是通過 Instrumentation 調用了 Activity 的 onCreate 方法。

mInstrumentation.callActivityOnCreate(activity, r.state);  

到此為止,Activity 完成了啟動。

5)Activity 的 onResume 方法,和 onDestroy 方法

ActivityStack.resumeTopActivityLocked()
ActivityStack.resumeTopInnerLocked()
IApplicationThread.scheduleResumeActivity()
ActivityThread.scheduleResumeActivity()
ActivityThread.sendMessage()
ActivityTherad.H.sendMessage()
ActivityThread.H.handleMessage()
ActivityThread.H.handleResumeMessage()
Activity.performResume()
Activity.performRestart()
Instrumentation.callActivityOnRestart()
Activity.onRestart()
Activity.performStart()
Instrumentation.callActivityOnStart()
Activity.onStart()
Instrumentation.callActivityOnResume()
Activity.onResume()

Activity.finish()
ActivityManagerNative.getDefault().finishActivity()
ActivityManagerService.finishActivity()
ActivityStack.requestFinishActivityLocked()
ActivityStack.finishActivityLocked()
ActivityStack.startPausingLocked()

onResume 回調和當 Activity 銷毀時的 onDestroy 回調都與前面的過程大同小異,這里就只列舉相應的方法棧,不再繼續描述。


總結

可以看到,Activity 的生命周期并不是一個類就可以簡單完成的,在這其中需要多個模塊之間進行通信合作,才能做到現在的效果。里面涉及到兩種 Android 中常見的通信方式,分別是 Binder 機制和 Handler 機制。其中 Binder 機制用于 ActivityThread 和 ActivityManagerService 進行進程間通信,而 Handler 機制,則用在 ActivityThread 中,使得 ActivityThread 在合適的時機能處理相應的生命周期。


文檔信息


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容