一:taskAffinity 屬性介紹
taskAffinity 是用來指示Activity屬于哪一個Task,前提是Activity的launchMod是否設置了SingleTask或者Flag_ACTIVITY_NEW_TASK
默認情況下,在一個App中的所有Activity都有一樣的taskAffinity,同屬在一個Task中,但是我們也可以設置不同的taskAffinity,也可以在不同的App中,設置相同的taskAffinity,以達到不同app的Activity共用同一個Task的目的。

Default 啟動模式
依次打開FirstActivity->SecondActivity->ThirdActivity->SecondActivity,查看log信息:
11-08 20:38:54.890 13971-13971/com.xplee.task.task I/xplee: ***************分割線****************
11-08 20:38:54.890 13971-13971/com.xplee.task.task I/xplee: task id:22 FirstActivity onCreate
11-08 20:38:58.510 13971-13971/com.xplee.task.task I/xplee: task id:22 SecondActivity onCreate
11-08 20:39:01.190 13971-13971/com.xplee.task.task I/xplee: task id:22 ThirdActivity onCreate
11-08 20:39:28.600 13971-13971/com.xplee.task.task I/xplee: task id:22 SecondActivity onCreate
SingleTask啟動模式
依次打開FirstActivity->SecondActivity->ThirdActivity->SecondActivity,查看log信息:
11-08 20:49:04.920 17645-17645/com.xplee.task.task I/xplee: ***************分割線****************
11-08 20:49:04.920 17645-17645/com.xplee.task.task I/xplee: task id:24 FirstActivity onCreate
11-08 20:49:15.300 17645-17645/com.xplee.task.task I/xplee: task id:24 SecondActivity onCreate
11-08 20:49:17.170 17645-17645/com.xplee.task.task I/xplee: task id:24 ThirdActivity onCreate
11-08 20:49:22.710 17645-17645/com.xplee.task.task I/xplee: task id:24 SecondActivity onNewIntent
11-08 20:49:23.060 17645-17645/com.xplee.task.task I/xplee: task id:24 ThirdActivity onDestroy
singleTask & different taskAffinity
依次打開FirstActivity->SecondActivity->ThirdActivity->SecondActivity,查看log信息:
11-08 20:58:18.300 22445-22445/com.xplee.task.task I/xplee: ***************分割線****************
11-08 20:58:18.310 22445-22445/com.xplee.task.task I/xplee: task id:26 FirstActivity onCreate
11-08 20:58:29.340 22445-22445/com.xplee.task.task I/xplee: task id:27 SecondActivity onCreate
11-08 20:58:30.920 22445-22445/com.xplee.task.task I/xplee: task id:27 ThirdActivity onCreate
11-08 20:58:33.140 22445-22445/com.xplee.task.task I/xplee: task id:27 SecondActivity onNewIntent
11-08 20:58:33.480 22445-22445/com.xplee.task.task I/xplee: task id:27 ThirdActivity onDestroy
從上面日志可以看出,僅當設置Activity為SingleTask或者FLAG_ACTIVITY _NEW_TASK的時候,設置taskAffinity屬性才會起效。
二:Android啟動模式
Standard標準模式
默認的啟動模式,每次跳轉激活都會重新生成一個新的Activity實例,并放入任務棧中。

SingleTop棧頂模式
如果在任務棧的棧頂正好存有該Activity的實例,則會通過調(diào)用onNewIntent方法進行重用,否則就會同Standard標準模式一樣,創(chuàng)建新的實例并放入棧頂。當且僅當啟動的Activity和上一個Activity一致的時候才會通過調(diào)用onNewIntent()方法重用Activity,使用場景: 資訊閱讀類App的內(nèi)容界面。

singleTask 單一任務模式
該啟動模式專門用于解決上面SingleTop的另外一種情況,只要棧中已經(jīng)存在的該Activity的實例,就會直接調(diào)用OnNewIntent()方法來實現(xiàn)重用實例,重用時候直接讓Activity實例回到棧頂,并且移除之前它上面的所有Activity實例。如果棧內(nèi)不存在該實例,則會重新創(chuàng)建,使用場景: 瀏覽器的主頁面或者大部分App的主界面。

singleInstance 啟動模式
在一個新棧中創(chuàng)建Activity實例,并讓多個應用共享棧中的該Activity實例,一旦該模式的Activity實例已經(jīng)存在于某個棧中,任何應用再激活調(diào)用該Activity時都會重用棧中的實例,值得注意的是,singleInstance不要用于中間頁面,如果用于中間頁面,跳轉會出現(xiàn)很難受的問題。

三:Intent標簽
我們一般在AndroidManifest.xml中設置 android:launchMode 啟動模式,那么還有其它方式來設置啟動模式嗎?下面我們通過Intent標簽來講講。
在Android中,除了通過配置文件來設置啟動模式,我們還可以在代碼中通過設置flag來設置啟動模式。
Intent.setFlag(int flags);
- FLAG_ACTIVITY_NEW_TASK 該標識會使新啟動的Activity獨立創(chuàng)建一個TASK
- FLAG_ACTIVITY_CLEAR_TOP 該標識會檢查啟動的Activity是否存在于Task中,如果存在,則會清除其之上的Activity,使它獲得焦點,并不重新實例化一個Activity,一般結合FLAG_ACTIVITY_NEW_TASK一起使用。
- FLAG_ACTIVITY_SINGLE_TOP 等同于在launcherMode屬性中設置為SingleTop
四:Android啟動流程和原理

Activity的啟動流程如上圖所示,Activity啟動跳轉都要經(jīng)過System_server層,并經(jīng)過其進行分發(fā)
A調(diào)用startActivty -----》 需要與AMS交互,此時需要獲取到AMS代理對象的Binder,即上圖中的AMP,
通過ActivityManagerNative.getDefault()獲得,并調(diào)用AMP的startActivity方法,通過mRemote.transact進行binder通信。
mRemote.transact(START_ACTIVITY_TRANSACTION,data,reply,0);
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags){
switch(code){
case START_ACTIVITY_TRANSACTION:{ startActivity(app,callingPackage,intent,...)
}
}}

1:startProcessLocked 方法首先調(diào)用Process.start("android.app.ActivityThread") 向Zygote發(fā)送一個啟動流程的request,并告訴Zygote進程啟動后,加載ActivityThread這個類的入口main函數(shù),啟動完成后,返回進程的pid,并向ams的handler發(fā)送一個延遲消息,為的是要求目標進程啟動后,10s內(nèi)需要向ams報告,否則ams會清除目標進程的相關信息
2: Process.start方法會調(diào)用startViaZygote()方法,該方法功能主要是 1:打開連接Zygote的socket,2:通過socket發(fā)送啟動進程的參數(shù)信息
3:Zygote端主要邏輯在runOnce方法中,該方法內(nèi)調(diào)用Zygote.forkAndSpecialize 方法創(chuàng)建子進程,創(chuàng)建完成之后,就分別在父子進程中做各自的事情
- 父進程通過handleParentProc(pid) 把子進程的pid通過socket發(fā)送給AMS
- 子進程通過調(diào)用handleChildProc函數(shù),做一些通用的初始化工作,比如啟用Binder機制,執(zhí)行應用程序的入口函數(shù)
4: ActivityThread中的systemMain方法中,會創(chuàng)建一個ActivityThread對象,并調(diào)用thread.attach方法,為的是向AMS發(fā)送一個延遲消息
5: attach方法中,有個跨進程的調(diào)用,首先調(diào)用
IActivityManager mgr = ActivityManagerNative.getDefault();
獲取到AMS的Binder代理對象,然后調(diào)用
mgr.attachApplication(mAppThread);
mAppThread是應用端的一個Binder對象ApplicationThread(ATP),這樣AMS端就可以調(diào)用應用端了。
其中要明白AMS里面有兩個棧,一個是Launch桌面棧,一個就是非桌面棧mFocusStack,此處的stack就是mFocusStack,它會將棧頂?shù)腁ctivityRecord返回出來,我們的目標Activity早就放置在了棧頂,只是一直沒有初始化,然后調(diào)用方法,來啟動Activity,如果我們不啟動另外一個進程,而是同一個進程,那么這第二大部分就不會存在了,而是直接調(diào)用realStartActivityLocked方法。
realStartActivityLocked(hr,app,true,true);
- realStartActivityLocked函數(shù)會調(diào)用app.thread.scheduleLaunchActivity(new Intent(r.intent),...);也就是通過之前注冊的Binder對象ATP,調(diào)用scheduleLaunchActivity函數(shù),在scheduleLaunchActivity函數(shù)里面:
ActivityClientRecord r = new ActivityClientRecord(); ... sendMessage(H.LAUNCH_ACTIVITY,r);
封裝了一個ActivityClientRecord消息,然后丟到主線程的Handler(mH)里。
2: 在主線程中
final ActivityClientRecord r = (ActivityClientRecord)msg.obj ;
r.packageInfo = getPackageInfoNoCheck(...);
handleLaunchActivity(r,null);
getPackageInfoNoCheck 函數(shù)主要是用來生成一個LoadedApk對象,它用來保存我們的apk信息,因為后面我們需要一個ClassLoader去加載Apk里面的Activity類,所以這里提前準備好。
3.handleLaunchActivity里面分為兩個部分,一個是performLaunchActivity函數(shù),一個是handleResumeActivity函數(shù)。
performLaunchActivity
Activity activity = mInstrumentation.newActivity(...);
//返回之前創(chuàng)建好的
Application app = r.packageInfo.makeApplication(false,mInstrumentation);
//生成ContextImpl
Context appContext = createBaseContextForActivity(r,activity);
//給activity綁定上下文和一些初始化的工作,如createPhoneWindow
activity.attach(appContext,...);
mInstrumentation.callActivityOnCreate(activity,r.state); //生命周期的OnCreate
activity.performStart(); //生命周期的OnStart
return activity
handleResumeActivity:
r.activity.performResume() -> mInstrumentation.callActivityOnResume(this);
-> activity.onResume()