閱讀這篇文章,需要對Binder有一定了解。我們通過從桌面啟動一個應用講解啟動一個安卓應用的流程。
遠程調用
這里要先明確一個概念,就是所謂的遠程調用即跨進程調用,安卓大部分情況下通過Binder來實現,其實現的大致原理,每個支持Binder的進程都有一個Binder線程池,當我們通過Binder遠程調用另一個進程的方法時,例如A進程遠程調用B進程的print方法,其過程是A進程把要調用的方法的方法描述(方法名,參數,身份確認信息等)裝進一個Parcel對象發送到Binder驅動,B進程中空閑的Binder線程會去取消息,當它取到消息后開始在B進程里運行,根據傳遞過來的方法描述去調用對應的方法,這樣兩個進程間就完成了一次跨進程的調用,屏蔽掉細節就變成了A進程調用了B進程的print方法,這里要注意的是,A進程往Binder驅動寫值后,可以選擇阻塞或不阻塞,也就是Binder的雙向還是單向模式,若調用模式為單向模式,A進程往Binder驅動寫入值后會立即返回,開始執行下一條指令,不在乎B進程是否正確處理了這個消息,而如果是雙向,則在A進程寫值后會一直等待,等待B進程處理完成print方法,再往Binder驅動回一條消息,A進程接收到這個消息后調用返回,開始執行下一條指令,這個過程就很像在同一個進程中調用方法了,想象若我們在A進程中也有同名方法print,這個方法的作用是往Binder驅動寫值并等待調用返回,而B進程收到消息并執行了B進程的print并在Binder驅動中寫回值,現在A進程收到寫回的消息,print返回,執行下一條指令,其過程就像是在A進程里執行了B進程的print方法一樣,足以讓使用者忽略掉這其實經過了跨進程的通信,而只是調用了一次普通方法。
幾個重要的類:
- ActivityManagerService (簡稱AMS),運行在system_server 進程,其實質為一個Binder服務端,與之對應的是 ActivityManagerProxy(簡稱AMP),運行在各個應用即客戶端,封裝了Binder操作,應用使用這個類遠程調用AMS
- ActivityThread,應用進程java層的根節點,其main方法為應用進程java層的起點,完成應用啟動初始化工作,并通過Binder和Handler負責應用與system_server進程間通信的消息轉發工作
- ApplicationThread,工作在應用進程,ActivityThread的成員變量,負責應用與system_server間的通信,與AMS功能對應,其作為Binder服務端,system_server通過ApplicationThreadProxy遠程調用ApplicationThread,從而調用ActivityThread的各個方法,經過ActivityThread的轉發,從而控制整個應用
- Instrumentation,ActivityThread對Activity生命周期的調用具體通過這個類實現
以下我們通過Launcher啟動一個應用來演示一個應用的啟動過程:
startActivity
通過Launcher啟動一個帶視圖的應用,即啟動一個Activity,此時這個Activity所需要依附的進程還未啟動:
首先我們在Launcher的main線程(即所謂UI線程)里調用startActivity,這個方法最終通過Instrumentation調用ActivityManagerProxy的同名方法,通過AMP遠程調用AMS(ActivityManagerService的同名方法),
打印main 線程的調用棧,調用從下到上,Activity的startActivity方法最終調到了AMP的startActivity,作為Binder客戶端這個startActivity的實現就是打包各種參數并傳到Binder驅動
main:
showStartingWindow
調到這里,因為AMS和AMP是實現了同一個接口的,所以在AMS作為服務端也有同名方法,下面是在system_server進程中,一個被啟動來處理這個消息的Binder線程的調用棧:
可以看到Binder在倒數第四行,調用了startActivity,下面三個函數啟動的作用就是取出并解析傳過來的數據,然后交給對應的方法處理,這里根據傳過來的方法id調用到了ActivityManagerService的startActivity方法,再經過層層調用,通知WMS顯示startingWindow,所謂startingWindow,就是系統為了應用之間的過渡平滑,應用在啟動之前,預先啟動起來的預覽視圖,這是應用的MainActivity的theme里面配置的,這個視圖的顯示速度很快,因為其不屬于應用進程,不需要等待應用初始化,往往在點擊應用圖標的瞬間就能顯示。
schedulePauseActivity
再看這次調用中另一個方法的調用棧:
調到了ApplicationThreadProxy(ATP)的schedulePauseActivity方法,看名字,就知道這又是一個Binder客戶端,這個Binder客戶端對應的Binder服務端在Launcher的進程里,名字叫ApplicationThread,system_server進程通過這個ATP可以跨進程調用Launcher的方法(每個應用進程都有一個ApplicationThread,可見system_server進程存有所有由它管理的進程的ATP,因為它需要通過這些ATP去管理所有應用進程,如控制應用組件的生命周期),到這里,整個調用鏈從Launcher進程的main線程,到system_server進程,現在又要回到Launcher,但是要注意,通過Binder再調回去之后,ApplicationThread的schedulepauseActivity方法就是在一個另起的Binder線程里了,main線程會繼續執行它后續的指令不受影響,我們現在查看Launcher里面這個另起的Binder線程的調用棧:
這里可以看到,在ApplicationThread的schedulepauseActivity方法里的處理,Binder線程往Handler里發送了一條消息,這個消息將由main線程來處理
activityPaused
此時我們查看主線程收到這個這個message之后的處理:
可以看到收到在handleMessage里,主線程調用了ActivityThread的handlePauseActivity,我們來看一下handlePauseActivity的實現,下面是幾行關鍵代碼:
performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
...
...
// Tell the activity manager we have paused.
if (!dontReport) {
try {
ActivityManagerNative.getDefault().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
performPauseActivity最終會調用到Activity的onPause方法(在這之前還會先調用Fragment的onPause),然后調用到ActivityManagerNative.getDefault().activityPaused(token)
也就是我們上圖調用棧所示的AMP的activityPaused方法。
到這里,整個流程還沒有走到一個新的Activity的創建甚至連新的應用進程都還沒有創建,Launcher與system_server兩個進程之間已經經過了來回各一次跨進程的調用。而到現在對應用開發者能實際感知的到的很重要的一點,就是當前Activity和Fragment走到到了生命周期onPause。應用開發者該在這里做狀態保存工作了。
Process.start
回到AMP的activityPaused方法,現在Launcher的主線程又要遠程調用AMS,system_server端會把這個調用交個一個空閑Binder線程去處理,我們查看其調用棧:
注意 ActivityStackSupervisor中的startSpecificActivityLocked方法,這個方法在這里會進入分水嶺,這里會檢查這個Activity需要依附的進程有沒有被創建,如果已經創建,則會進入realStartActivityLocked方法,遠程調會Launcher進程,實例化要啟動的Activity,并依次調用其onCreate,onStart,onResume生命周期方法(當然其中各個方法的調用都是經過各個類層層調用,但如果從應用開發的角度來說就是這個調用順序,期間不需要再由AMS干預),但對應進程如果不存在,則還需要調用AMS的startProcess創建這個進程,如上調用棧棧頂走到Process類的start方法,注意調用這個方法時傳遞的一個參數,entryPoint,這里是android.app.ActivityThread
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
checkTime(startTime, "startProcess: returned from zygote!");
傳遞這個參數,新進程在啟動之后就會調用這個類的main方法作為java層的起點(java層第一個方法應該是ZygoInit的main,但在調用棧中根據傳過來的參數分成別反射調用了SystemServer和ActiviThread的main,我們習慣上把這兩個函數當成起點),至于Process.start的實現,這里先不深究,大致過程,zygote進程與system_server之間通過socket通信,要創建進程時,system_server 進程里通過往socket寫入消息,zygote接收到消息后fork出一個進程,最終會調用ActivityThread的main函數,下面看一下創建進程需要的參數:
* Starts a new process via the zygote mechanism.
*
* @param processClass Class name whose static main() to run
* @param niceName 'nice' process name to appear in ps
* @param uid a POSIX uid that the new process should setuid() to
* @param gid a POSIX gid that the new process shuold setgid() to
* @param gids null-ok; a list of supplementary group IDs that the
* new process should setgroup() to.
* @param debugFlags Additional flags.
* @param targetSdkVersion The target SDK version for the app.
* @param seInfo null-ok SELinux information for the new process.
* @param abi the ABI the process should use.
* @param instructionSet null-ok the instruction set to use.
* @param appDataDir null-ok the data directory of the app.
* @param extraArgs Additional arguments to supply to the zygote process.
* @return An object that describes the result of the attempt to start the process.
* @throws ZygoteStartFailedEx if process start failed for any reason
*/
其實現:
/**
* See com.android.internal.os.ZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
writer.flush();
---
---
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
往流里寫入值各種參數,再從流里讀回返回信息,具體的實現就是zygote進程的事了。
至此,一個應用進程就已經啟動,我們進入android.app.ActivityThread的main方法,我們可以當這里是應用的起點。
ActivityThread.main
從 ActivityThread 的main方法開始,應用進入 java 層,應用在main里面的關鍵代碼:
public static void main(String[] args) {
... ...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
... ...
Looper.loop();
}
主要的三件事:
調用Looper.prepareMainLooper 創建mainLooper并賦值給Loop (這個looper的MessageQueue不能quit)靜態變量 sMainLooper ,這樣應用可以在任何地方拿到主線程的Looper
-
創建ActivityThread實例,并調用attach,這兩步很關鍵,首先,ActivityThread對象創建時,會創建ResourcesManager的單例對象,還會創建 ApplicationThread 對象作為匿名Binder服務端用以跟system_server進程通信,在thread.attach(false) 中通過AMP把 這個對象注冊到AMS:
final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); }
AMS 對各應用組件的生命周期管理就是通過這個對象實現的,AMS會通過這個ApplicationThread 對象遠程調用應用進程的方法從而實現管理。
?
另外在attach 方法里ActivityThread對象會把自己賦值給靜態變量sCurrentActivityThread,在應用開發中可以通過反射ActivityThread 直接拿到這個靜態變量對象或反射后調用靜態方法 currentActivityThread()拿到應用的ActivityThread 對象,從而可以拿到其成員變量mAppThread,mInstrumentation,插件化方案可能需要hook這兩個對象。
?
主線程啟動loop,進入循環,等待其他線程往消息隊列里發消息
attachApplication
遠程調用AMS的attachApplication方法后,會輾轉到系統進場中AMS的attachApplicationLocked,通過ProcessRecord.makeActive將這個IApplicationThread 傳入與進程相關的ProcessRecord,這個對象與每個用戶進程相對應, 這樣system_server進程就持有了應用的一個Binder,之后就可以通過這個Binder給應用發消息,從而管理應用了。
bindApplication
之后system_server進程通過thread.bindApplication遠程調用應用進程的ApplicationThread的同名方法,同之前的其他調用,應用進程里bindApplication這個方法是運行在某個binder線程的,這里這個Binder線程調用這個方法通過handler即成員變量mH把消息丟給了主線程,主線程收到消息轉到ActivityThread的handleBindApplication方法,查看調用棧
system_server:
從attachApplication 調用到 bindApplication,整個調用過程由應用發起,將ApplicationThread傳遞給AMS(attachApplication這個方法最主要的功能就是把ApplicatioThread傳遞給了system_server進程,從此應用進程和system_server進程可以互相通信),然后AMS拿到這個ApplicationThread的客戶端ATP,調用其bindApplication,這樣調用又走回了應用,應用會在bindApplication里面做一些初始化工作,如實例化Instrumentation,實例化Application,并賦值給mInitialApplication = app;這個變量的賦值是唯一的,只會有這一次,也就是一個進程應用進程只會有一個mInitialApplication,但是,這并不意味著一個進程只有一個Application實例,一個進程里是有可能創建多個Application實例的,比如下面要講的handleLaunchActivity方法,每啟動一個Activity,都會去判斷這個Activity對應的Application有沒有被實例化,若沒有,則會創建,并添加到mAllApplications列表,這種情況會在兩個應用共用進程時出現。mInitialApplication賦值后,會作為參數啟動provider。
bindApplication:
// Allow disk access during application and provider setup. This could
// block processing ordered broadcasts, but later processing would
// probably end up doing the same disk access.
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
//這里只會實例化Application,而不會調用其onCreate
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
//初始化ContentProvider
installContentProviders(app, data.providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
//調用Application.onCreate
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
final ArrayList<IActivityManager.ContentProviderHolder> results =
new ArrayList<IActivityManager.ContentProviderHolder>();
for (ProviderInfo cpi : providers) {
if (DEBUG_PROVIDER) {
StringBuilder buf = new StringBuilder(128);
buf.append("Pub ");
buf.append(cpi.authority);
buf.append(": ");
buf.append(cpi.name);
Log.i(TAG, buf.toString());
}
//這個context就是mInitialApplication,這里會實例化provider
//installProvider方法里會為每個provider賦值一個context,這個Context有可能是 //mInitialApplication本身,也可能是根據不同包名重新創建的
//這個方法里還會調用ContentProvider的onCreate生命周期方法
//要注意,直到這里,我們還在ActivityThread的bindApplication方法里,這是AMS對應用進程的第 //一個遠程調用,我們雖然已經創建了Application實例,但我們還沒有調用其onCreate,還沒有任何 //Activity和Service組件被實例化,而在這里,所有ContentProvider已經完成創建,調用 //onCreate并注冊到AMS了
IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
//注冊到AMS
try {
ActivityManagerNative.getDefault().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
bindApplication完成后,到這里應用進程已經先后完成了Application的實例化,ContentProvider的實例化和onCreate生命周期,Application的onCreate生命周期。
scheduleLaunchActivity
注意AMS里面 attachApplicationLocked方法,除了遠程調用ActivityThread的bindApplication外,還調用了其scheduleLaunchActivity方法,這個方法最終會實例化一個Activity,調用其生命周期方法。先來看system_server端的調用棧:
下面是上面兩次遠程調用,轉到應用進程后對應的兩次處理,都是Binder線程收到消息后重新丟到主線程里后主線程的調用棧。
handleLaunchActivity是應用進程收到的第二個system_server的遠程調用(通過handler中轉過的),我們來看一下主線程在handleLaunchActivity里做了什么:
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
... ...
// Initialize before creating the activity
WindowManagerGlobal.initialize();
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);
... ...
}
performLaunchActivity得到了一個Activity,之后調用了handleResumeActivity,這里方法里就會調用Activity的onResume生命周期方法。再看在這之前performLaunchActivity的邏輯:
Activity activity = null;
try {
//反射實例化Activity
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);
}
}
try {
//拿到Application,這個Application是之前已經創建的,若對應的Application之前沒有創建
//則會先實例化,這種情況出現在一個應用進程承載多個應用時,啟動第一個之外的其他應用時應用進程
//已經創建并與AMS綁定,所以不會走bindApplication方法,所以新應用對應的Application是還沒有
//創建的,需要先創建。
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
... ...
if (activity != null) {
//這里實際是一個ContextImpl實例
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;
}
//典型裝飾者模式,Activity的很多功能會委托給ContextImpl實例實現
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);
}
... ...
//Activity.onStart
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
///Activity.onRestoreInstanceState
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);
}
}
利用Instrumentation反射創建Activity,然后r.packageInfo.makeApplication(false, mInstrumentation),這個方法會判斷當前應用(注意是應用而不是進程)有沒有Application實例,若沒有,則創建,創建其ContextImpl,調用其生命周期方法onCreate,注意Application app = r.packageInfo.makeApplication(false, mInstrumentation);
這個方法,其實現末尾處有一段判斷
if (mApplication != null) {
return mApplication;//這里作為應用進程第一個被創建的Application,在bindApplication里就完成了實例化和生命周期onCreate,這里直接返回
}
//這里省略了反射實例化Application的代碼
... ...
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
... ...
}
}
若傳遞的instrumentation不為空,則調用其onCreate,之前在bindAppliction里面調用傳遞參數是空,所以只是實例化了Application,這里在參數不為空,如果這個Application不是應用進程的第一個Application,那么會在這里實例化并調用onCreate 。
Activity.attach
可以看出,如果同一個進程運行多個應用的話,除了一個應用外,一個應用的第一個Activity會比Application先實例化,只是生命周期的調用時機在Application后面。Activity的創建過程是先反射創建其實例,然后作為參數創建其委托對象ContextImpl,然后attach這個對象,將ContextImpl作為自己的成員變量,很多功能會委托給這個對象實現,除此之外Activity.attach方法還會為創建PhoneWindow作為成員變量。
callActivityOnCreate
attach之后,來到mInstrumentation.callActivityOnCreate,這里會調用Activity的onCreate,activity.performStart,調用activity.onStart,mInstrumentation.callActivityOnRestoreInstanceState,調用Activity.onRestoreInstanceState,performLaunchActivity 方法返回之后,handleLaunchActivity繼續走到ActivityThread.handleResumeActivity,調用Activity.onResume 。這些方法里面還夾雜Fragment的管理,這里先忽略。
scheduleStopActivity
至此,完成這個應用啟動需要走的所有生命周期,而Launcher我們只分析到OnPause,一個完整的過程它是需要走到onStop才對的,我們看下在Launcher的ActivityThread調用ams的activityPaused里面,AMS除了通知Zygote孵化新進程外還做了什么,我們先回顧下創建應用進程的調用棧,:
Launcher在走完onPause生命周期后,就會通知AMS去啟動新的Activity,而啟動時發現對應的進程還沒創建,所以這里先創建進程,這之后AMS就等著新啟動的進程走到java層的attach方法來注冊自己。
我們看上面這個調用里,在completePausedLocked方法里,還有另一個調用,看下面的調用棧:
往Handler里面發了一條消息,這個handler攜帶的消息會在system_server的一個Looper子線程里被處理,我們看其處理的調用棧:
這里就會去調用經過Binder和Handler中轉,就會走到Launcher的的onStop生命周期了。
回顧
到這里大家可以回顧一下兩個應用的的Activity生命周期是怎么走的,首先Launcher向AMS發消息要啟動一個Activity,AMS發消息回來,讓Launcher走到onPause,然后Launcher告訴AMS onPause已經調用,這個“告訴”的過程中往system_server的一個Looper線程中發了條消息,這個消息收到后就會再回過來調用到Launcher的onStop,同時,還通過Process.start通知Zygote孵化出要啟動的應用進程,應用進程啟動后通過AMP.attachApplication注冊自己的ApplicationThread到AMS,AMS回過來通過ApplicationThread調用了應用的bindApplication和scheduleLaunchActivity,前者完成Application對象實例化,Instrumentation初始化,ContentProvider的實例化和onCreate調用,Application的onCreate的調用,后者完成Activity的實例化,以及onCreate,onStart,onResume 連續三個生命周期的調用。這里可以看出兩點:
- Application的實例化是在ContentProvider之前的,但是Application的onCreate調用時機其實是在ContentProvider的onCreate之后的。
- Launcher的onStop的調用其實和被啟動的應用的Activity的生命周期是沒有絕對的順序的,但它的onPause肯定是要先被調用的(而在這之前還會通知WMS顯示應用的startingWindow),其調用時機甚至比新應用進程的創建還早,AMS會等它被調用后才通知Zygote孵化新進程(其實也不絕對,想象如果onPause耗時太久,必然會影響新進程的啟動了,這里AMS會有超時機制,超過500毫秒還沒有通知AMS activityPaused,AMS就會不再等待,直接創建新進程)