Activity、Task、應用和進程

//如下Activity中,launchmode如其名: HomeActivity --> 
//                                StandardActivity --> 
//                                singleTaskActivity --> 
//                                singleInstanceActivity -->
//                                standardActivity -->
//                                CameraActivity(調用系統相機方法)
// adb shell dumpsys activity
Stack #1:
    Task id #5
      TaskRecord{7546973 #5 A=com.e_gavin163.listest U=0 sz=5}
      Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.e_gavin163.listest/.task_test.HomeActivity }
        Hist #4: ActivityRecord{700d91d u0 com.android.camera/.CameraActivity t5}
          Intent { act=android.media.action.IMAGE_CAPTURE cmp=com.android.camera/.CameraActivity }
          ProcessRecord{d91c03e 25810:com.android.camera/u0a81}
        Hist #3: ActivityRecord{e341be0 u0 com.e_gavin163.listest/.task_test.StandardActity t5}
          Intent { flg=0x10400000 cmp=com.e_gavin163.listest/.task_test.StandardActity }
          ProcessRecord{79171f5 26358:com.e_gavin163.listest/u0a110}
        Hist #2: ActivityRecord{faf6cf1 u0 com.e_gavin163.listest/.task_test.SingleTaskActivity t5}
          Intent { flg=0x10000000 cmp=com.e_gavin163.listest/.task_test.SingleTaskActivity }
          ProcessRecord{79171f5 26358:com.e_gavin163.listest/u0a110}
        Hist #1: ActivityRecord{a4a7fb9 u0 com.e_gavin163.listest/.task_test.StandardActity t5}
          Intent { cmp=com.e_gavin163.listest/.task_test.StandardActity }
          ProcessRecord{79171f5 26358:com.e_gavin163.listest/u0a110}
        Hist #0: ActivityRecord{9e21af3 u0 com.e_gavin163.listest/.task_test.HomeActivity t5}
          Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.e_gavin163.listest/.task_test.HomeActivity }
          ProcessRecord{79171f5 26358:com.e_gavin163.listest/u0a110}
    Task id #6
      TaskRecord{db084a9 #6 A=com.e_gavin163.listest U=0 sz=1}
      Intent { flg=0x10000000 cmp=com.e_gavin163.listest/.task_test.SingleInstanceActivity }
        Hist #0: ActivityRecord{fac5462 u0 com.e_gavin163.listest/.task_test.SingleInstanceActivity t6}
          Intent { flg=0x10000000 cmp=com.e_gavin163.listest/.task_test.SingleInstanceActivity }
          ProcessRecord{79171f5 26358:com.e_gavin163.listest/u0a110}

    Running activities (most recent first):
      TaskRecord{7546973 #5 A=com.e_gavin163.listest U=0 sz=5}
        Run #5: ActivityRecord{700d91d u0 com.android.camera/.CameraActivity t5}
        Run #4: ActivityRecord{e341be0 u0 com.e_gavin163.listest/.task_test.StandardActity t5}
      TaskRecord{db084a9 #6 A=com.e_gavin163.listest U=0 sz=1}
        Run #3: ActivityRecord{fac5462 u0 com.e_gavin163.listest/.task_test.SingleInstanceActivity t6}
      TaskRecord{7546973 #5 A=com.e_gavin163.listest U=0 sz=5}
        Run #2: ActivityRecord{faf6cf1 u0 com.e_gavin163.listest/.task_test.SingleTaskActivity t5}
        Run #1: ActivityRecord{a4a7fb9 u0 com.e_gavin163.listest/.task_test.StandardActity t5}
        Run #0: ActivityRecord{9e21af3 u0 com.e_gavin163.listest/.task_test.HomeActivity t5}

    mResumedActivity: ActivityRecord{700d91d u0 com.android.camera/.CameraActivity t5}

  Stack #0:
          .
          .
          .
個人總結:
  1. 一個應用程序只有一個任務棧(Stack)
  2. 一個應用程序可以有多個Task(一個Task表現于回退棧,按返回鍵可以推出最上面的Activity
  3. 只有SingleInstance會新建一個Task,而不在當前回退棧里面;在SingleInstance模式的Activity里面startActivity,新建的ActivityTaskID也是之前主TaskID,而不會是SingleInstanceTaskIDSingleInstance獨占一個TaskID.
  4. 在當前Activity中調用其他應用的ActivityB,ActivityB會添加到當前應用程序的棧中,并且和當前ActivityTaskID(AcitivytBlaunchMode不為SingleInstance情況下)。但是不同processActivityB只會跑在自己的process中。

以下內容轉自franksunny


很想弄清楚啟動一個ActivityTask(任務)的關系,網上也有很多相關資料,由從源碼來具體分析的,也有針對launchmode來分析,但都不是自己的,理解起來總不是那么容易,為此,嘗試著自己去理解其中的邏輯。不過事先需要弄清楚兩個問題:

誰負責管理Activity?

Androidframework框架中采用C/S的方式實現由后臺服務ActivityManagerService(很多書上將其簡稱為Ams)來管理具體的Acitivity實例,雖然Ams命名為ActivityManagerService,但是它其實不僅僅管理Activity,他還管理除Acitvity外的其它三大組件,還包括Intentpendingintentapk進程和task等等,具體可以查看源碼frameworks\base\services\java\com\android\server\am下面的Ams源碼和相關的*Record類。
??網上資料顯示在2.3以后的SDK中,Ams將原來的HistoryRecord類重新命名為ActivityRecord類,并將其原來Ams中的一些處理抽出來成為一個ActivityStack類,每一個Activity實例對應一個ActivityRecord對象,并存放在ActivityStack中,手機一旦啟動,就會啟動一個Ams服務,在Ams服務中有一個ActivityStack實例專門管理手機上的ActivityRecord實例。這樣一來,不具體分析源碼,僅從架構角度來說誰負責管理Activity的問題就清晰多了。

Task到底是什么?

根據對上面問題的解答,既然Activity是由Ams通過ActivityStack來管理的,那么這個Task又是干什么的呢?
??以往基于應用(application)的程序開發中,程序具有明確的邊界,一個程序就是一個應用,一個應用為了實現功能可以采用開辟新線程甚至新進程來輔助,但是應用與應用之間不能復用資源和功能。而Android引入了基于組件開發的軟件架構,雖然我們開發android程序,仍然使用一個apk工程一個Application的開發形式,但是對于Aplication的開發就用到了Activityservice等四大組件,其中的每一個組件,都是可以被跨應用復用的哦,這個就是android的神奇之處。
??另外值得一提的是,雖然組件可以跨應用被調用,但是一個組件所在的進程必須是在組件所在的Aplication進程中。由于android強化了組件概念,弱化了Aplication的概念,所以在android程序開發中,A應用的A組件想要使用拍照或錄像的功能就可以不用去針對Camera類進行開發,直接調用系統自帶的攝像頭應用(稱其B應用)中的組件(稱其B組件)就可以了,但是這就引發了一個新問題,A組件跑在A應用中,B組件跑在B應用中,自然都不在同一個進程中,那么從B組件中返回的時候,如何實現正確返回到A組件呢?Task就是來負責實現這個功能的,它是從用戶角度來理解應用而建立的一個抽象概念。因為用戶所能看到的組件就是Activity,所以Task可以理解為實現一個功能而負責管理所有用到的Activity實例的棧。
??其實查看源碼,在Ams內部,并不是真的有這么一個存放ActivityTask棧,Activity還是通過ActivityStack來管理,在ActivityRecord中有一個TaskRecord對象記錄了真實的Activity實例是屬于哪個Task的。Task通過一個int類型的TaskId來唯一標識,該值在手機重啟時將會被置零。
??說了這么多,還是找一個Task任務最直觀的體現吧。先重啟手機,長按home鍵,發現彈出的最近任務中一個任務也沒有,然后開啟A應用,長按home鍵,會發現有一個A應用的任務,查看手機進程,應該還沒有B進程的;在A應用的A組件中調B應用的B組件,此時看手機的進程,除了A進程外,還有個B的進程,但是長按home鍵,能看到的還是只有一個A應用的任務。其實這個時候,B應用已經跑起來了,但是對用戶來說,他其實沒有開啟過B應用,所以Task任務自始至終都是從用戶的角度出發而設計的概念,保證用戶的調用邏輯。

Activity、Application與進程的關系

理清楚了上述兩個概念問題,進入Activity的啟動與Task的關系之前,讓我們先來了解下啟動一個Activityapk Application和進程的關系。對Activity啟動過程具體的分析,工程耗時很龐大,網上有個老羅整理的三篇博客,我看了半天還是云里霧里的。我通過我現在的認識和目前通過Demo的測試來看,啟動一個Activity時,Ams首先會去查詢該Activity所在的應用是否開啟,如果沒有開啟則會啟動一個進程去Run這個Application,因此無論通過Launcher還是通過常規的程序內部調用startActivity來啟動一個Activity,所要啟動的Activity都是跑在其注冊的apk所在的Application進程中(或者該組件android:process指定的進程中),而其TaskID一般是和啟動它的組件所屬的TaskId一致,但是也不盡然,這就要看下面的具體分析了。
??另外通過對service的應用,可以得出結論,一個apk,即一個應用(Application)可以跑在多個進程中,一個進程在一個虛擬機中運行,也即一個apk可以啟動多個虛擬機。
??通過shareuserID可以將多個apk,跑在同一個進程中。
??從而得出結論:一個虛擬機只能跑一個進程,一個進程里可以跑多個應用,一個應用也可以跑在多個進程中,這就是他們的關系。

Activity和Task的關系

啟動一個Activity有兩種方式,一種就是通過Launcher,另外一種是通過程序代碼調用startActivity函數實現(驗證過AppWidget其實與這種方式是一致的)其實影響Activity啟動關鍵點大致有三個因素:Activity注冊信息中的launchMode、啟動ActivityIntent中的launchFlagsActivity注冊信息中的taskAffinity、allowTaskReparentingclearTaskOnLaunchalwaysRetainTaskStatefinishOnTaskLaunch等信息。通常情況下,我們只需要針對第一個因素進行合理設置就能滿足我們應用開發的需求了。
??launchMode的四種方式
??launchMode方法是在apkmanifest文件中針對每一個Activityandroid:launchMode屬性進行設置的方式,共有四種模式可以設置,分別是standard、singleTop、singleTask、singleInstance,下面分別闡述之(由于其中幾種因素有設置時,會影響lauchMode的四種模式,所以下面情況下,其它因素都是缺省不設置的情況)。

standard

standard是默認模式,即假設用戶在manifest中對Activity不指定android:launchMode的情況下,缺省啟動模式即為standard。在啟動一個以standardlaunchModeActivity時,Ams只是簡單的創建一個新的Activity實例,將其放到ActivityStack(為了行文方便,后面將ActivityStack簡稱AS),其TaskId則與啟動這個Activity的調用者Activity相同(即就算創建一個新的進程,但是其TaskId還是跟調用者一致的,以確保用戶回退操作時保持一致)。這種是最常見的使用方式。

singleTop

啟動一個以singleToplauchModeActivity時,Ams會查詢AS:假如在AS頂端正是要啟動的Activity實例,那么Ams就不會重新啟動一個Activity實例,而是調用AS棧頂的該Activity實例的OnNewIntent函數(自然不會修改原來的TaskId值);假如在AS棧頂不是該Activity的實例,那么就會創建一個新的實例,將其壓入AS,其TaskId與調用者Activity相同。這種方式主要用于避免自調自過程中,產生多個實例的情況。

singleTask

啟動一個以singleTasklauchModeActivity時,Ams會查詢AS:如果AS內有一個該類Activity的實例,那么就會將該實例置于TS的頂端(原來位于該實例上面的其它同TaskIdactivity實例,將被銷毀),并調用該實例的onNewIntent函數;如果AS內沒有該類的實例,就會啟動一個新的實例,將其壓入AS,其TaskID與啟動它的調用者沒有必然關系,而是取決于該Activity所在apk進程是否有TaskId,假如沒有就會創建一個新的TaskId。在實測中發現,如果singleTask模式啟動的ActivityAS中同TaskId的最底部一個(或被稱謂Task棧的根實例),那么在通過桌面長按,在近期任務中跳轉到Activity所在的任務時,即使該Activity實例不是在棧頂,也會被置到棧頂(還會調用其onNewIntent函數),并將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
 
//通過長按跳轉到TaskOne任務,此時在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

啟動一個以singleInstancelaunchmodeActivity時,假如AS中已經有一個該類實例,那么調用其onNewIntent函數;否則就會創建一個新的TaskId,與該Activity所在的apk進程完全不同的TaskId,而且這個TaskId值以后也不會被用于其他任何Activity實例中。

簡單小結

一般我們開發普通的應用程序時,我們只需要使用缺省的standardsingleTop方式就夠用了,不需要使用singleTasksingleInstance來聲明注冊的Activity,因為它將破壞用戶感覺上的回退操作,給用戶使用上帶來迷惑,所以一般將這兩者用于很耗資源的Activity,通過查看源碼發現在源碼packages\apps中的程序,有如下一些應用使用了這兩者高級設置

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"

在上述分析中沒有將其它兩個因素引入,主要是自己在這方面接觸的也比較少,而且這三方面因素共同組合會產生很多種不同效果,所以就沒做具體展開。轉載一些網友收集的資料如下:

跟Task有關的manifest文件中Activity的特性值介紹

android:allowTaskReparenting

用來標記Activity能否從啟動的Task移動到有著affinityTask(當這個Task進入到前臺時)
??“true”,表示能移動,“false”,表示它必須呆在啟動時呆在的那個Task里。
??如果這個特性沒有被設定,設定到<application>元素上的allowTaskReparenting特性的值會應用到Activity上。默認值為“false”
??一般來說,當Activity啟動后,它就與啟動它的Task關聯,并且在那里耗盡它的整個生命周期。當當前的Task不再顯示時,你可以使用這個特性來強制Activity移動到有著affinityTask中。典型用法是:把一個應用程序的Activity移到另一個應用程序的主Task中。
??例如,如果 email中包含一個web頁的鏈接,點擊它就會啟動一個Activity來顯示這個頁面。這個Activity是由Browser應用程序定義的,但是,現在它作為email Task的一部分。如果它重新宿主到Browser Task里,當Browser下一次進入到前臺時,它就能被看見,并且,當email Task再次進入前臺時,就看不到它了。
??Actvityaffinity是由taskAffinity特性定義的。Taskaffinity是通過讀取根Activityaffinity決定。因此,根Activity總是位于相同affinityTask里。由于啟動模式為“singleTask”“singleInstance”Activity只能位于Task的底部,因此,重新宿主只能限于“standard”“singleTop”模式。

android:alwaysRetainTaskState

用來標記Activity所在的Task的狀態是否總是由系統來保持。
??“true”,表示總是;“false”,表示在某種情形下允許系統恢復Task到它的初始化狀態。默認值是“false”
??這個特性只針對Task的根Activity有意義;對其它Activity來說,忽略之。
??一般來說,特定的情形如當用戶從主畫面重新選擇這個Task時,系統會對這個Task進行清理(從stack中刪除位于根Activity之上的所有Activivity)。典型的情況,當用戶有一段時間沒有訪問這個Task時也會這么做,例如30分鐘。
??然而,當這個特性設為“true”時,用戶總是能回到這個Task的最新狀態,無論他們是如何啟動的。這非常有用,例如,像Browser應用程序,這里有很多的狀態(例如多個打開的Tab),用戶不想丟失這些狀態。

android:clearTaskOnLaunch

用來標記是否從Task中清除所有的Activity,除了根Activity外(每當從主畫面重新啟動時)
??“true”,表示總是清除至它的根Activity“false”表示不。默認值是“false”
??這個特性只對啟動一個新的TaskActivity(根Activity)有意義;對Task中其它的Activity忽略。
??當這個值為“true”,每次用戶重新啟動這個Task時,都會進入到它的根Activity中,不管這個Task最后在做些什么,也不管用戶是使用BACK還是HOME離開的。當這個值為“false”時,可能會在一些情形下(參考alwaysRetainTaskState特性)清除TaskActivity,但不總是。
??假設,某人從主畫面啟動了Activity P,并從那里遷移至Activity Q。接下來用戶按下HOME,然后返回Activity P。一般,用戶可能見到的是Activity Q,因為它是PTask中最后工作的內容。然而,如果P設定這個特性為“true”,當用戶按下HOME并使這個Task再次進入前臺時,其上的所有的Activity(在這里是Q)都將被清除。因此,當返回到這個Task時,用戶只能看到P
??如果這個特性和allowTaskReparenting都設定為“true”,那些能重新宿主的Activity會移動到共享affinityTask中;剩下的Activity都將被拋棄,如上所述。

android:finishOnTaskLaunch

用來標記當用戶再次啟動它的Task(在主畫面選擇這個Task)時已經存在的Activity實例是否要關閉(結束)
?“true”,表示應該關閉,“false”表示不關閉。默認值是“false”
?如果這個特性和allowTaskReparenting都設定為“true”,這個特性勝出。Activityaffinity忽略。這個Activity不會重新宿主,但是會銷毀。

android:launchMode

用于指示Activity如何啟動。這里有四種模式,與Intent對象中的Activity Flags(FLAG_ACTIVITY_*變量)共同作用,來決定Activity如何啟動來處理Intent。它們是:
??"standard"
??"singleTop"
??"singleTask"
??"singleInstance"
??默認模式是“standard”
??前面文章:“Android四種Activity的加載模式”已經詳細描述,這里就不做描述了.

android:noHistory

用于標記當用戶從Activity上離開并且它在屏幕上不再可見時Activity是否從Activity stack中清除并結束(調用finish()方法)——“true”,表示它應該關閉,“false”,表示不需要。默認值是“false”
??“true”值意味著Activity不會留下歷史痕跡。因為它不會在Activity stackTask中保留,因此,用戶不能返回它。
??比如啟用界面的就可以借用這個。

android:taskAffinity

這就是本文所描述的任務共用性。
??ActivityTask擁有的一個affinity。擁有相同的affinityActivity理論上屬于相同的Task(在用戶的角度是相同的“應用程序”)。Taskaffinity是由它的根Activity決定的。
??affinity決定兩件事情——Activity重新宿主的Task(參考allowTaskReparenting特性)和使用FLAG_ACTIVITY_NEW_TASK標志啟動的Activity宿主的Task
??默認情況,一個應用程序中的所有Activity都擁有相同的affinity。捏可以設定這個特性來重組它們,甚至可以把不同應用程序中定義的Activity放置到相同的Task中。為了明確Activity不宿主特定的Task,設定該特性為空的字符串。
??如果這個特性沒有設置,Activity將從應用程序的設定那里繼承下來(參考<application>元素的taskAffinity特性)。應用程序默認的affinity的名字是<manifest>元素中設定的package名。

跟Task有關的Intent對象中設置的Flag

FLAG_ACTIVITY_BROUGHT_TO_FRONT

這個標志一般不是由程序代碼設置的,如在launchMode中設置singleTask模式時系統幫你設定。

FLAG_ACTIVITY_CLEAR_TOP

如果設置,并且這個Activity已經在當前的Task中運行,因此,不再是重新啟動一個這個Activity的實例,而是在這個Activity上方的所有Activity都將關閉,然后這個Intent會作為一個新的Intent投遞到老的Activity(現在位于頂端)中。
??例如,假設一個Task中包含這些Activity:A,B,C,D。如果D調用了startActivity(),并且包含一個指向Activity BIntent,那么,C和D都將結束,然后B接收到這個Intent,因此,目前stack的狀況是:A,B。
??上例中正在運行的Activity B既可以在onNewIntent()中接收到這個新的Intent,也可以把自己關閉然后重新啟動來接收這個Intent。如果它的啟動模式聲明為“multiple”(默認值),并且你沒有在這個Intent中設置FLAG_ACTIVITY_SINGLE_TOP標志,那么它將關閉然后重新創建;對于其它的啟動模式,或者在這個Intent中設置FLAG_ACTIVITY_SINGLE_TOP標志,都將把這個Intent投遞到當前這個實例的onNewIntent()中。
??這個啟動模式還可以與FLAG_ACTIVITY_NEW_TASK結合起來使用:用于啟動一個Task中的根Activity,它會把那個Task中任何運行的實例帶入前臺,然后清除它直到根Activity。這非常有用,例如,當從Notification Manager處啟動一個Activity

FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

如果設置,這將在TaskActivity stack中設置一個還原點,當Task恢復時,需要清理Activity。也就是說,下一次Task帶著FLAG_ACTIVITY_RESET_TASK_IF_NEEDED標記進入前臺時(典型的操作是用戶在主畫面重啟它),這個Activity和它之上的都將關閉,以至于用戶不能再返回到它們,但是可以回到之前的Activity
??這在你的程序有分割點的時候很有用。例如,一個e-mail應用程序可能有一個操作是查看一個附件,需要啟動圖片瀏覽Activity來顯示。這個Activity應該作為e-mail應用程序Task的一部分,因為這是用戶在這個Task中觸發的操作。然而,當用戶離開這個Task,然后從主畫面選擇e-mail app,我們可能希望回到查看的會話中,但不是查看圖片附件,因為這讓人困惑。通過在啟動圖片瀏覽時設定這個標志,瀏覽及其它啟動的Activity在下次用戶返回到mail程序時都將全部清除。

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

如果設置,新的Activity不會在最近啟動的Activity的列表中保存。

FLAG_ACTIVITY_FORWARD_RESULT

如果設置,并且這個Intent用于從一個存在的Activity啟動一個新的Activity,那么,這個作為答復目標的Activity將會傳到這個新的Activity中。這種方式下,新的Activity可以調用setResult(int),并且這個結果值將發送給那個作為答復目標的Activity

FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

這個標志一般不由應用程序代碼設置,如果這個Activity是從歷史記錄里啟動的(常按HOME鍵),那么,系統會幫你設定。

FLAG_ACTIVITY_MULTIPLE_TASK

不要使用這個標志,除非你自己實現了應用程序啟動器。與FLAG_ACTIVITY_NEW_TASK結合起來使用,可以禁用把已存的Task送入前臺的行為。當設置時,新的Task總是會啟動來處理Intent,而不管這是是否已經有一個Task可以處理相同的事情。
??由于默認的系統不包含圖形Task管理功能,因此,你不應該使用這個標志,除非你提供給用戶一種方式可以返回到已經啟動的Task。
??如果FLAG_ACTIVITY_NEW_TASK標志沒有設置,這個標志被忽略。

FLAG_ACTIVITY_NEW_TASK

如果設置,這個Activity會成為歷史stack中一個新Task的開始。一個Task(從啟動它的Activity到下一個Task中的Activity)定義了用戶可以遷移的Activity原子組。Task可以移動到前臺和后臺;在某個特定Task中的所有Activity總是保持相同的次序。
??這個標志一般用于呈現“啟動”類型的行為:它們提供用戶一系列可以單獨完成的事情,與啟動它們的Activity完全無關。
??使用這個標志,如果正在啟動的ActivityTask已經在運行的話,那么,新的Activity將不會啟動;代替的,當前Task會簡單的移入前臺。參考FLAG_ACTIVITY_MULTIPLE_TASK標志,可以禁用這一行為。
??這個標志不能用于調用方對已經啟動的Activity請求結果。

FLAG_ACTIVITY_NO_ANIMATION

如果在Intent中設置,并傳遞給Context.startActivity()的話,這個標志將阻止系統進入下一個Activity時應用Acitivity遷移動畫。這并不意味著動畫將永不運行——如果另一個Activity在啟動顯示之前,沒有指定這個標志,那么,動畫將被應用。這個標志可以很好的用于執行一連串的操作,而動畫被看作是更高一級的事件的驅動。

FLAG_ACTIVITY_NO_HISTORY

如果設置,新的Activity將不再歷史stack中保留。用戶一離開它,這個Activity就關閉了。這也可以通過設置noHistory特性。

FLAG_ACTIVITY_NO_USER_ACTION

如果設置,作為新啟動的Activity進入前臺時,這個標志將在Activity暫停之前阻止從最前方的Activity回調的onUserLeaveHint()
??典型的,一個Activity可以依賴這個回調指明顯式的用戶動作引起的Activity移出后臺。這個回調在Activity的生命周期中標記一個合適的點,并關閉一些Notification
??如果一個Activity通過非用戶驅動的事件,如來電或鬧鐘,啟動的,這個標志也應該傳遞給Context.startActivity,保證暫停的Activity不認為用戶已經知曉其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中設置,并傳遞給Context.startActivity(),這個標志將引發已經運行的Activity移動到歷史stack的頂端。
??例如,假設一個Task由四個Activity組成:A,B,C,D。如果D調用startActivity()來啟動Activity B,那么,B會移動到歷史stack的頂端,現在的次序變成A,C,D,B。如果FLAG_ACTIVITY_CLEAR_TOP標志也設置的話,那么這個標志將被忽略。

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

如果設置,當這個Activity位于歷史stack的頂端運行時,不再啟動一個新的。

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

推薦閱讀更多精彩內容