Activity、Task、应用和进程
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
?為了閱讀方便,將文檔轉(zhuǎn)成pdf?
http://files.cnblogs.com/franksunny/ActivityTask%E5%BA%94%E7%94%A8%E5%92%8C%E8%BF%9B%E7%A8%8B%E5%B0%8F%E7%BB%93.pdf
Activity、Task、應(yīng)用和進程
?
很想弄清楚啟動一個Activity和Task(任務(wù))的關(guān)系,網(wǎng)上也有很多相關(guān)資料,由從源碼來具體分析的,也有針對launchmode來分析,但都不是自己的,理解起來總不是那么容易,為此,嘗試著自己去理解其中的邏輯。不過事先需要弄清楚兩個問題:
誰負責管理Activity?
Android的framework框架中采用C/S的方式實現(xiàn)由后臺服務(wù)ActivityManagerService(很多書上將其簡稱為 Ams)來管理具體的Acitivity實例,雖然Ams命名為ActivityManagerService,但是它其實不僅僅管理Activity, 他還管理除Acitvity外的其它三大組件,還包括Intent、pendingintent、apk進程和task等等,具體可以查看源碼 frameworks\base\services\java\com\android\server\am下面的Ams源碼和相關(guān)的*Record類。
網(wǎng)上資料顯示在2.3以后的SDK中,Ams將原來的HistoryRecord類重新命名為ActivityRecord類,并將其原來Ams中 的一些處理抽出來成為一個ActivityStack類,每一個Activity實例對應(yīng)一個ActivityRecord對象,并存放在 ActivityStack中,手機一旦啟動,就會啟動一個Ams服務(wù),在Ams服務(wù)中有一個ActivityStack實例專門管理手機上的 ActivityRecord實例。這樣一來,不具體分析源碼,僅從架構(gòu)角度來說誰負責管理Activity的問題就清晰多了。
Task到底是什么?
根據(jù)對上面問題的解答,既然Activity是由Ams通過ActivityStack來管理的,那么這個Task又是干什么的呢?
以往基于應(yīng)用(application)的程序開發(fā)中,程序具有明確的邊界,一個程序就是一個應(yīng)用,一個應(yīng)用為了實現(xiàn)功能可以采用開辟新線程甚至新 進程來輔助,但是應(yīng)用與應(yīng)用之間不能復(fù)用資源和功能。而Android引入了基于組件開發(fā)的軟件架構(gòu),雖然我們開發(fā)android程序,仍然使用一個 apk工程一個Application的開發(fā)形式,但是對于Aplication的開發(fā)就用到了Activity、service等四大組件,其中的每一 個組件,都是可以被跨應(yīng)用復(fù)用的哦,這個就是android的神奇之處。
另外值得一提的是,雖然組件可以跨應(yīng)用被調(diào)用,但是一個組件所在的進程必須是在組件所在的Aplication進程中。由于android強化了組 件概念,弱化了Aplication的概念,所以在android程序開發(fā)中,A應(yīng)用的A組件想要使用拍照或錄像的功能就可以不用去針對Camera類進 行開發(fā),直接調(diào)用系統(tǒng)自帶的攝像頭應(yīng)用(稱其B應(yīng)用)中的組件(稱其B組件)就可以了,但是這就引發(fā)了一個新問題,A組件跑在A應(yīng)用中,B組件跑在B應(yīng)用 中,自然都不在同一個進程中,那么從B組件中返回的時候,如何實現(xiàn)正確返回到A組件呢?Task就是來負責實現(xiàn)這個功能的,它是從用戶角度來理解應(yīng)用而建 立的一個抽象概念。因為用戶所能看到的組件就是Activity,所以Task可以理解為實現(xiàn)一個功能而負責管理所有用到的Activity實例的棧。
其實查看源碼,在Ams內(nèi)部,并不是真的有這么一個存放Activity的Task棧,Activity還是通過ActivityStack來管 理,在ActivityRecord中有一個TaskRecord對象記錄了真實的Activity實例是屬于哪個Task的。Task通過一個int類 型的TaskId來唯一標識,該值在手機重啟時將會被置零。
說了這么多,還是找一個Task任務(wù)最直觀的體現(xiàn)吧。先重啟手機,長按home鍵,發(fā)現(xiàn)彈出的最近任務(wù)中一個任務(wù)也沒有,然后開啟A應(yīng)用,長按 home鍵,會發(fā)現(xiàn)有一個A應(yīng)用的任務(wù),查看手機進程,應(yīng)該還沒有B進程的;在A應(yīng)用的A組件中調(diào)B應(yīng)用的B組件,此時看手機的進程,除了A進程外,還有 個B的進程,但是長按home鍵,能看到的還是只有一個A應(yīng)用的任務(wù)。其實這個時候,B應(yīng)用已經(jīng)跑起來了,但是對用戶來說,他其實沒有開啟過B應(yīng)用,所以 Task任務(wù)自始至終都是從用戶的角度出發(fā)而設(shè)計的概念,保證用戶的調(diào)用邏輯。
Activity、Application與進程的關(guān)系
理清楚了上述兩個概念問題,進入Activity的啟動與Task的關(guān)系之前,讓我們先來了解下啟動一個Activity與apk Application和進程的關(guān)系。對Activity啟動過程具體的分析,工程耗時很龐大,網(wǎng)上有個老羅整理的三篇博客,我看了半天還是云里霧里的, 有興趣的可以查看如下鏈接:http://blog.csdn.net/luoshengyang/article/details/6685853。 我通過我現(xiàn)在的認識和目前通過Demo的測試來看,啟動一個Activity時,Ams首先會去查詢該Activity所在的應(yīng)用是否開啟,如果沒有開啟 則會啟動一個進程去Run這個Application,因此無論通過Launcher還是通過常規(guī)的程序內(nèi)部調(diào)用startActivity來啟動一個 Activity,所要啟動的Activity都是跑在其注冊的apk所在的Application進程中(或者該組件android:process指 定的進程中),而其TaskID一般是和啟動它的組件所屬的TaskId一直,但是也不盡然,這就要看下面的具體分析了。
另外通過對service的應(yīng)用,可以得出結(jié)論,一個apk,即一個應(yīng)用(Application)可以跑在多個進程中,一個進程在一個虛擬機中運行,也即一個apk可以啟動多個虛擬機。
通過shareuserID可以將多個apk,跑在同一個進程中。
從而得出結(jié)論:一個虛擬機只能跑一個進程,一個進程里可以跑多個應(yīng)用,一個應(yīng)用也可以跑在多個進程中,這就是他們的關(guān)系。
Activity和Task的關(guān)系
啟動一個Activity有兩種方式,一種就是通過Launcher,另外一種是通過程序代碼調(diào)用startActivity函數(shù)實現(xiàn)(驗證過 AppWidget其實與這種方式是一致的)其實影響Activity啟動關(guān)鍵點大致有三個因素:Activity注冊信息中的launchMode、啟 動Activity時Intent中的launchFlags和Activity注冊信息中的taskAffinity、 allowTaskReparenting、clearTaskOnLaunch、alwaysRetainTaskState、 finishOnTaskLaunch等信息。通常情況下,我們只需要針對第一個因素進行合理設(shè)置就能滿足我們應(yīng)用開發(fā)的需求了。
launchMode的四種方式
launchMode方法是在apk的manifest文件中針對每一個Activity的android:launchMode屬性進行設(shè)置的方 式,共有四種模式可以設(shè)置,分別是standard、singleTop、singleTask、singleInstance,下面分別闡述之(由于其 中幾種因素有設(shè)置時,會影響lauchMode的四種模式,所以下面情況下,其它因素都是缺省不設(shè)置的情況)。
standard
standard是默認模式,即假設(shè)用戶在manifest中對Activity不指定android:launchMode的情況下,缺省啟動模 式即為standard。在啟動一個以standard為launchMode的Activity時,Ams只是簡單的創(chuàng)建一個新的Activity實 例,將其放到ActivityStack(為了行文方便,后面將ActivityStack簡稱AS),其TaskId則與啟動這個Activity的調(diào) 用者Activity相同(即就算創(chuàng)建一個新的進程,但是其TaskId還是跟調(diào)用者一致的,以確保用戶回退操作時保持一致)。這種是最常見的使用方式。
singleTop
啟動一個以singleTop為lauchMode的Activity時,Ams會查詢AS:假如在AS頂端正是要啟動的Activity實例,那 么Ams就不會重新啟動一個Activity實例,而是調(diào)用AS棧頂?shù)脑揂ctivity實例的OnNewIntent函數(shù)(自然不會修改原來的 TaskId值);假如在AS棧頂不是該Activity的實例,那么就會創(chuàng)建一個新的實例,將其壓入AS,其TaskId與調(diào)用者Activity相 同。這種方式主要用于避免自調(diào)自過程中,產(chǎn)生多個實例的情況。
singleTask
啟動一個以singleTask為lauchMode的Activity時,Ams會查詢AS:如果AS內(nèi)有一個該類Activity的實例,那么 就會將該實例置于TS的頂端(原來位于該實例上面的其它同TaskId的activity實例,將被銷毀),并調(diào)用該實例的onNewIntent函數(shù); 如果AS內(nèi)沒有該類的實例,就會啟動一個新的實例,將其壓入AS,其TaskID與啟動它的調(diào)用者沒有必然關(guān)系,而是取決于該Activity所在apk 進程是否有TaskId,假如沒有就會創(chuàng)建一個新的TaskId。在實測中發(fā)現(xiàn),如果singleTask模式啟動的Activity是AS中同 TaskId的最底部一個(或被稱謂Task棧的根實例),那么在通過桌面長按,在近期任務(wù)中跳轉(zhuǎn)到Activity所在的任務(wù)時,即使該 Activity實例不是在棧頂,也會被置到棧頂(還會調(diào)用其onNewIntent函數(shù)),并將AS上同TaskId的其它Activity實例銷毀, 具體可以通過附帶的demo來驗證,其中TaskOne中的Activity1置成singleTask啟動模式,其它均為默認的standard,其 log輸出如下:
//在TaskTwo中啟動Activity1,此前TaskOne apk沒有在運行,所以啟動Activity1時會申請一個新的TaskId,2afcfbd8這個Activity1成為了TaskId為53的Task棧棧底實例
04-05 16:21:27.144: E/ActivityB @2b003230(17933): onPause pid 17933 taskid 52
04-05 16:21:27.404: E/Activity1 @2afcfbd8(18489): onCreate pid 18489 taskid 53
04-05 16:21:29.214: E/ActivityB @2afecaf0(17933): onCreate pid 17933 taskid 53
04-05 16:21:30.254: E/Activity2 @2afdeef0(18489): onCreate pid 18489 taskid 53
04-05 16:21:30.894: E/ActivityB @2aff9328(17933): onCreate pid 17933 taskid 53
04-05 16:21:31.454: E/Activity2 @2afe9330(18489): onCreate pid 18489 taskid 53
04-05 16:21:31.864: E/ActivityB @2b009910(17933): onCreate pid 17933 taskid 53
04-05 16:21:32.424: E/Activity2 @2aff2570(18489): onCreate pid 18489 taskid 53
?
//通過長按跳轉(zhuǎn)到TaskOne任務(wù),此時在AS中id為53的在Activity1上面有6個
04-05 16:22:35.144: E/ActivityB @2afecaf0(17933): onDestroy pid 17933 taskid 53
04-05 16:22:35.144: E/Activity2 @2afdeef0(18489): onDestroy pid 18489 taskid 53
04-05 16:22:35.234: E/ActivityB @2aff9328(17933): onDestroy pid 17933 taskid 53
04-05 16:22:35.254: E/Activity2 @2afe9330(18489): onDestroy pid 18489 taskid 53
04-05 16:22:35.324: E/ActivityB @2b009910(17933): onDestroy pid 17933 taskid 53
04-05 16:22:35.344: E/Activity2 @2aff2570(18489): onPause pid 18489 taskid 53
04-05 16:22:35.394: E/Activity1 @2afcfbd8(18489): onNewIntent pid 18489 taskid 53
04-05 16:22:35.394: E/Activity1 @2afcfbd8(18489): onStart pid 18489 taskid 53
04-05 16:22:35.394: E/Activity1 @2afcfbd8(18489): onResume pid 18489 taskid 53
04-05 16:22:35.524: E/Activity2 @2aff2570(18489): onStop pid 18489 taskid 53
04-05 16:22:35.524: E/Activity2 @2aff2570(18489): onDestroy pid 18489 taskid 53
singleInstance
啟動一個以singleInstance為launchmode的Activity時,假如AS中已經(jīng)有一個該類實例,那么調(diào)用其 onNewIntent函數(shù);否則就會創(chuàng)建一個新的TaskId,與該Activity所在的apk進程完全不同的TaskId,而且這個TaskId值 以后也不會被用于其他任何Activity實例中。
簡單小結(jié)
一般我們開發(fā)普通的應(yīng)用程序時,我們只需要使用缺省的standard和singTop方式就夠用了,不需要使用singleTask和 singleInstance來聲明注冊的Activity,因為它將破壞用戶感覺上的回退操作,給用戶使用上帶來迷惑,所以一般將這兩者用于很耗資源的 Activity,通過查看源碼發(fā)現(xiàn)在源碼packages\apps中的程序,有如下一些應(yīng)用使用了這兩者高級設(shè)置
AndroidManifest.xml (packages\apps\browser):????????????????? android:launchMode="singleTask"
AndroidManifest.xml (packages\apps\calendar):??????? <activity android:name="AlertActivity" android:launchMode="singleInstance"
AndroidManifest.xml (packages\apps\contacts):??????????? android:launchMode="singleTask"
AndroidManifest.xml (packages\apps\deskclock):??????????????? android:launchMode="singleInstance"
AndroidManifest.xml (packages\apps\deskclock):??????????????? android:launchMode="singleInstance"
AndroidManifest.xml (packages\apps\deskclock):??????????????? android:launchMode="singleInstance"
AndroidManifest.xml (packages\apps\email):??????????? android:launchMode="singleTask"
AndroidManifest.xml (packages\apps\launcher2):??????????? android:launchMode="singleTask"
AndroidManifest.xml (packages\apps\music):??????????????? android:launchMode="singleTask"
AndroidManifest.xml (packages\apps\phone):??????????? android:launchMode="singleInstance"
AndroidManifest.xml (packages\apps\phone):??????????? android:launchMode="singleInstance">
AndroidManifest.xml (packages\apps\quicksearchbox):????????????????? android:launchMode="singleTask"
AndroidManifest.xml (packages\apps\settings):????????????????? android:launchMode="singleTask"
AndroidManifest.xml (packages\providers\downloadprovider):????????????????? android:launchMode="singleTask"
在上述分析中沒有將其它兩個因素引入,主要是自己在這方面接觸的也比較少,而且這三方面因素共同組合會產(chǎn)生很多種不同效果,所以就沒做具體展開。轉(zhuǎn)載一些網(wǎng)友收集的資料如下:
跟Task有關(guān)的manifest文件中Activity的特性值介紹
android:allowTaskReparenting
??? 用來標記Activity能否從啟動的Task移動到有著affinity的Task(當這個Task進入到前臺時)
?? “true”,表示能移動,“false”,表示它必須呆在啟動時呆在的那個Task里。
??? 如果這個特性沒有被設(shè)定,設(shè)定到<application>元素上的allowTaskReparenting特性的值會應(yīng)用到Activity上。默認值為“false”。
??? 一般來說,當Activity啟動后,它就與啟動它的Task關(guān)聯(lián),并且在那里耗盡它的整個生命周期。當當前的Task不再顯示時,你可以使用這個特性來 強制Activity移動到有著affinity的Task中。典型用法是:把一個應(yīng)用程序的Activity移到另一個應(yīng)用程序的主Task中。
??? 例如,如果 email中包含一個web頁的鏈接,點擊它就會啟動一個Activity來顯示這個頁面。這個Activity是由Browser應(yīng)用程序定義的,但 是,現(xiàn)在它作為email Task的一部分。如果它重新宿主到Browser Task里,當Browser下一次進入到前臺時,它就能被看見,并且,當email Task再次進入前臺時,就看不到它了。
??? Actvity的affinity是由taskAffinity特性定義的。Task的affinity是通過讀取根Activity的affinity 決定。因此,根Activity總是位于相同affinity的Task里。由于啟動模式為“singleTask”和“singleInstance” 的Activity只能位于Task的底部,因此,重新宿主只能限于“standard”和“singleTop”模式。
android:alwaysRetainTaskState
??? 用來標記Activity所在的Task的狀態(tài)是否總是由系統(tǒng)來保持。
??? “true”,表示總是;“false”,表示在某種情形下允許系統(tǒng)恢復(fù)Task到它的初始化狀態(tài)。默認值是“false”。
??? 這個特性只針對Task的根Activity有意義;對其它Activity來說,忽略之。
??? 一般來說,特定的情形如當用戶從主畫面重新選擇這個Task時,系統(tǒng)會對這個Task進行清理(從stack中刪除位于根Activity之上的所有Activivity)。典型的情況,當用戶有一段時間沒有訪問這個Task時也會這么做,例如30分鐘。
??? 然而,當這個特性設(shè)為“true”時,用戶總是能回到這個Task的最新狀態(tài),無論他們是如何啟動的。這非常有用,例如,像Browser應(yīng)用程序,這里有很多的狀態(tài)(例如多個打開的Tab),用戶不想丟失這些狀態(tài)。
android:clearTaskOnLaunch
??? 用來標記是否從Task中清除所有的Activity,除了根Activity外(每當從主畫面重新啟動時)
?? “true”,表示總是清除至它的根Activity,“false”表示不。默認值是“false”。
??? 這個特性只對啟動一個新的Task的Activity(根Activity)有意義;對Task中其它的Activity忽略。
??? 當這個值為“true”,每次用戶重新啟動這個Task時,都會進入到它的根Activity中,不管這個Task最后在做些什么,也不管用戶是使用 BACK還是HOME離開的。當這個值為“false”時,可能會在一些情形下(參考alwaysRetainTaskState特性)清除Task的 Activity,但不總是。
??? 假設(shè),某人從主畫面啟動了Activity P,并從那里遷移至Activity Q。接下來用戶按下HOME,然后返回Activity P。一般,用戶可能見到的是Activity Q,因為它是P的Task中最后工作的內(nèi)容。然而,如果P設(shè)定這個特性為“true”,當用戶按下HOME并使這個Task再次進入前臺時,其上的所有的 Activity(在這里是Q)都將被清除。因此,當返回到這個Task時,用戶只能看到P。
??? 如果這個特性和allowTaskReparenting都設(shè)定為“true”,那些能重新宿主的Activity會移動到共享affinity的Task中;剩下的Activity都將被拋棄,如上所述。
android:finishOnTaskLaunch
??? 用來標記當用戶再次啟動它的Task(在主畫面選擇這個Task)時已經(jīng)存在的Activity實例是否要關(guān)閉(結(jié)束)
?? “true”,表示應(yīng)該關(guān)閉,“false”表示不關(guān)閉。默認值是“false”。
??? 如果這個特性和allowTaskReparenting都設(shè)定為“true”,這個特性勝出。Activity的affinity忽略。這個Activity不會重新宿主,但是會銷毀。
android:launchMode
??? 用于指示Activity如何啟動。這里有四種模式,與Intent對象中的Activity Flags(FLAG_ACTIVITY_*變量)共同作用,來決定Activity如何啟動來處理Intent。它們是:
??? "standard"
??? "singleTop"
??? "singleTask"
??? "singleInstance"
??? 默認模式是“standard”。
??? 前面文章:“Android四種Activity的加載模式”已經(jīng)詳細描述,這里就不做描述了.
android:noHistory
??? 用于標記當用戶從Activity上離開并且它在屏幕上不再可見時Activity是否從Activity stack中清除并結(jié)束(調(diào)用finish()方法)——“true”,表示它應(yīng)該關(guān)閉,“false”,表示不需要。默認值是“false”。
??? “true”值意味著Activity不會留下歷史痕跡。因為它不會在Activity stack的Task中保留,因此,用戶不能返回它。
??? 比如啟用界面的就可以借用這個。
android:taskAffinity
?? 這就是本文所描述的任務(wù)共用性。
?? Activity為Task擁有的一個affinity。擁有相同的affinity的Activity理論上屬于相同的Task(在用戶的角度是相同的“應(yīng)用程序”)。Task的affinity是由它的根Activity決定的。
?? affinity決定兩件事情——Activity重新宿主的Task(參考allowTaskReparenting特性)和使用FLAG_ACTIVITY_NEW_TASK標志啟動的Activity宿主的Task。
??? 默認情況,一個應(yīng)用程序中的所有Activity都擁有相同的affinity。捏可以設(shè)定這個特性來重組它們,甚至可以把不同應(yīng)用程序中定義的Activity放置到相同的Task中。為了明確Activity不宿主特定的Task,設(shè)定該特性為空的字符串。
??? 如果這個特性沒有設(shè)置,Activity將從應(yīng)用程序的設(shè)定那里繼承下來(參考<application>元素的taskAffinity特 性)。應(yīng)用程序默認的affinity的名字是<manifest>元素中設(shè)定的package名。
跟Task有關(guān)的Intent對象中設(shè)置的Flag
FLAG_ACTIVITY_BROUGHT_TO_FRONT
??? 這個標志一般不是由程序代碼設(shè)置的,如在launchMode中設(shè)置singleTask模式時系統(tǒng)幫你設(shè)定。
FLAG_ACTIVITY_CLEAR_TOP
??? 如果設(shè)置,并且這個Activity已經(jīng)在當前的Task中運行,因此,不再是重新啟動一個這個Activity的實例,而是在這個Activity上方 的所有Activity都將關(guān)閉,然后這個Intent會作為一個新的Intent投遞到老的Activity(現(xiàn)在位于頂端)中。
??? 例如,假設(shè)一個Task中包含這些Activity:A,B,C,D。如果D調(diào)用了startActivity(),并且包含一個指向Activity B的Intent,那么,C和D都將結(jié)束,然后B接收到這個Intent,因此,目前stack的狀況是:A,B。
??? 上例中正在運行的Activity B既可以在onNewIntent()中接收到這個新的Intent,也可以把自己關(guān)閉然后重新啟動來接收這個Intent。如果它的啟動模式聲明為 “multiple”(默認值),并且你沒有在這個Intent中設(shè)置FLAG_ACTIVITY_SINGLE_TOP標志,那么它將關(guān)閉然后重新創(chuàng) 建;對于其它的啟動模式,或者在這個Intent中設(shè)置FLAG_ACTIVITY_SINGLE_TOP標志,都將把這個Intent投遞到當前這個實 例的onNewIntent()中。
??? 這個啟動模式還可以與FLAG_ACTIVITY_NEW_TASK結(jié)合起來使用:用于啟動一個Task中的根Activity,它會把那個Task中任 何運行的實例帶入前臺,然后清除它直到根Activity。這非常有用,例如,當從Notification Manager處啟動一個Activity。
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
??? 如果設(shè)置,這將在Task的Activity stack中設(shè)置一個還原點,當Task恢復(fù)時,需要清理Activity。也就是說,下一次Task帶著 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED標記進入前臺時(典型的操作是用戶在主畫面重啟它),這個Activity和它之 上的都將關(guān)閉,以至于用戶不能再返回到它們,但是可以回到之前的Activity。
??? 這在你的程序有分割點的時候很有用。例如,一個e-mail應(yīng)用程序可能有一個操作是查看一個附件,需要啟動圖片瀏覽Activity來顯示。這個 Activity應(yīng)該作為e-mail應(yīng)用程序Task的一部分,因為這是用戶在這個Task中觸發(fā)的操作。然而,當用戶離開這個Task,然后從主畫面 選擇e-mail app,我們可能希望回到查看的會話中,但不是查看圖片附件,因為這讓人困惑。通過在啟動圖片瀏覽時設(shè)定這個標志,瀏覽及其它啟動的Activity在下 次用戶返回到mail程序時都將全部清除。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
??? 如果設(shè)置,新的Activity不會在最近啟動的Activity的列表中保存。
FLAG_ACTIVITY_FORWARD_RESULT
??? 如果設(shè)置,并且這個Intent用于從一個存在的Activity啟動一個新的Activity,那么,這個作為答復(fù)目標的Activity將會傳到這個 新的Activity中。這種方式下,新的Activity可以調(diào)用setResult(int),并且這個結(jié)果值將發(fā)送給那個作為答復(fù)目標的 Activity。
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
??? 這個標志一般不由應(yīng)用程序代碼設(shè)置,如果這個Activity是從歷史記錄里啟動的(常按HOME鍵),那么,系統(tǒng)會幫你設(shè)定。
FLAG_ACTIVITY_MULTIPLE_TASK
??? 不要使用這個標志,除非你自己實現(xiàn)了應(yīng)用程序啟動器。與FLAG_ACTIVITY_NEW_TASK結(jié)合起來使用,可以禁用把已存的Task送入前臺的 行為。當設(shè)置時,新的Task總是會啟動來處理Intent,而不管這是是否已經(jīng)有一個Task可以處理相同的事情。
??? 由于默認的系統(tǒng)不包含圖形Task管理功能,因此,你不應(yīng)該使用這個標志,除非你提供給用戶一種方式可以返回到已經(jīng)啟動的Task。
??? 如果FLAG_ACTIVITY_NEW_TASK標志沒有設(shè)置,這個標志被忽略。
FLAG_ACTIVITY_NEW_TASK
??? 如果設(shè)置,這個Activity會成為歷史stack中一個新Task的開始。一個Task(從啟動它的Activity到下一個Task中的 Activity)定義了用戶可以遷移的Activity原子組。Task可以移動到前臺和后臺;在某個特定Task中的所有Activity總是保持相 同的次序。
??? 這個標志一般用于呈現(xiàn)“啟動”類型的行為:它們提供用戶一系列可以單獨完成的事情,與啟動它們的Activity完全無關(guān)。
??? 使用這個標志,如果正在啟動的Activity的Task已經(jīng)在運行的話,那么,新的Activity將不會啟動;代替的,當前Task會簡單的移入前臺。參考FLAG_ACTIVITY_MULTIPLE_TASK標志,可以禁用這一行為。
??? 這個標志不能用于調(diào)用方對已經(jīng)啟動的Activity請求結(jié)果。
FLAG_ACTIVITY_NO_ANIMATION
??? 如果在Intent中設(shè)置,并傳遞給Context.startActivity()的話,這個標志將阻止系統(tǒng)進入下一個Activity時應(yīng)用 Acitivity遷移動畫。這并不意味著動畫將永不運行——如果另一個Activity在啟動顯示之前,沒有指定這個標志,那么,動畫將被應(yīng)用。這個標 志可以很好的用于執(zhí)行一連串的操作,而動畫被看作是更高一級的事件的驅(qū)動。
FLAG_ACTIVITY_NO_HISTORY
??? 如果設(shè)置,新的Activity將不再歷史stack中保留。用戶一離開它,這個Activity就關(guān)閉了。這也可以通過設(shè)置noHistory特性。
FLAG_ACTIVITY_NO_USER_ACTION
??? 如果設(shè)置,作為新啟動的Activity進入前臺時,這個標志將在Activity暫停之前阻止從最前方的Activity回調(diào)的onUserLeaveHint()。
??? 典型的,一個Activity可以依賴這個回調(diào)指明顯式的用戶動作引起的Activity移出后臺。這個回調(diào)在Activity的生命周期中標記一個合適的點,并關(guān)閉一些Notification。
??? 如果一個Activity通過非用戶驅(qū)動的事件,如來電或鬧鐘,啟動的,這個標志也應(yīng)該傳遞給Context.startActivity,保證暫停的Activity不認為用戶已經(jīng)知曉其Notification。
FLAG_ACTIVITY_PREVIOUS_IS_TOP
??? If set and this intent is being used to launch a new activity from an existing one, the current activity will not be counted as the top activity for deciding whether the new intent should be delivered to the top instead of starting a new one. The previous activity will be used as the top, with the assumption being that the current activity will finish itself immediately.
FLAG_ACTIVITY_REORDER_TO_FRONT
??? 如果在Intent中設(shè)置,并傳遞給Context.startActivity(),這個標志將引發(fā)已經(jīng)運行的Activity移動到歷史stack的頂端。
??? 例如,假設(shè)一個Task由四個Activity組成:A,B,C,D。如果D調(diào)用startActivity()來啟動Activity B,那么,B會移動到歷史stack的頂端,現(xiàn)在的次序變成A,C,D,B。如果FLAG_ACTIVITY_CLEAR_TOP標志也設(shè)置的話,那么這 個標志將被忽略。
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task. This will result in the application of any affinities needed to have that task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed.
FLAG_ACTIVITY_SINGLE_TOP
??? 如果設(shè)置,當這個Activity位于歷史stack的頂端運行時,不再啟動一個新的。
轉(zhuǎn)載于:https://my.oschina.net/bintojojo/blog/340699
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的Activity、Task、应用和进程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android下的Junit测试
- 下一篇: 更改UISearchBar button