android Activity啓動模式

Activity的啓動模式有兩種:一種是在AndroidManifest.xml文件中,配置launchMode屬性,還有一種是設置intent的flag的方式來啓動java

一、設置android:launchMode屬性

    能夠分爲四種:standard、singleTop、singleTask、singleInstanceandroid

    standard:默認值。系統不考慮此Activity的實例是否已經在Back Stack中存在。每次建立都會啓動一個新的Activityshell

    singleTop:啓動時,棧頂恰好就是目標Activity,則調用此Activity的onNewIntent()便可。若是不是,則建立新的Activity實例spa

    singleTask:整個應用程序的上下文只有一個實例。當啓動此類Activity的時候,系統會從Back Stack中檢查是否已經存在此Activity的實例。            若是存在,會直接使用,並將此實例之上的Activity出棧,依然會毀掉onNewIntent().若是沒有就會建立一個新的實例。翻譯

    singleInstance:此Activity獨享一個Back Stack。主要用於程序之間的數據共享。code

    下面以例子來解釋:xml

    具體的代碼的設定模式以下:生命週期

<activity
            android:name=".launchmodeTest.StandardAActivity"
            android:label="A">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".launchmodeTest.SingleTopActivity" android:launchMode="singleTop" android:label="棧頂複用"/>
        <activity android:name=".launchmodeTest.SingleTaskActivity" android:launchMode="singleTask" android:label="棧內複用"/>
        <activity android:name=".launchmodeTest.SingleInstanceActivity" android:launchMode="singleInstance" android:label="單獨的一個棧"/>
        <activity android:name=".launchmodeTest.StandardCActivity" android:label="C"></activity>

   1.1 singleTop 棧頂複用:

            1.1.1 啓動步驟爲:StandardAActivity-->SingleTopActivity-->StandardCActivity-->SingleTopActivity進程

                執行adb shell dumpsys activity命令,在堆棧中的代碼爲(截取了其中一部分):字符串

Running activities (most recent first):
    TaskRecord{528b8768 #5 A base.example.com U 0}
      Run #4: ActivityRecord{528ddc64 u0 base.example.com/.launchmodeTest.SingleTopActivity}
      Run #3: ActivityRecord{52897c50 u0 base.example.com/.launchmodeTest.StandardCActivity}
      Run #2: ActivityRecord{5288e658 u0 base.example.com/.launchmodeTest.SingleTopActivity}
      Run #1: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

         分析說明:

                a、其中有兩個堆棧:

                    前臺堆棧:TaskRecord{528d7cd8 #6 A base.example.com U 0}

                    後臺堆棧:TaskRecord{528c8b7c #2 A com.android.launcher U 0}

                b、桌面:Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

        1.1.2 啓動步驟爲:StandardAActivity-->SingleTopActivity-->SingleTopActivity

                執行adb shell dumpsys activity命令,在堆棧中的代碼爲(截取了其中一部分):

Running activities (most recent first):
    TaskRecord{528d7cd8 #6 A base.example.com U 0}
      Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleTopActivity}
      Run #1: ActivityRecord{528b78c0 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                能夠看到,SingleTopActivity兩次啓動,可是只有一個實例。

                其中,生命週期爲

11-28 03:22:01.499 1831-1831/base.example.com I/SingleTopActivity: onPause: 
11-28 03:22:01.499 1831-1831/base.example.com I/SingleTopActivity: onNewIntent: 
11-28 03:22:01.499 1831-1831/base.example.com I/SingleTopActivity: onResume:

            1.2  singleTask 棧內複用

                   啓動步驟爲:StandardAActivity-->SingleTaskActivity-->StandardCActivity   

                   堆棧爲:

Running activities (most recent first):
    TaskRecord{528764c0 #8 A base.example.com U 0}
      Run #3: ActivityRecord{5289a4a0 u0 base.example.com/.launchmodeTest.StandardCActivity}
      Run #2: ActivityRecord{52889940 u0 base.example.com/.launchmodeTest.SingleTaskActivity}
      Run #1: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                   再啓動SingleTaskActivity

                   堆棧爲: 

Running activities (most recent first):
    TaskRecord{528764c0 #8 A base.example.com U 0}
      Run #2: ActivityRecord{52889940 u0 base.example.com/.launchmodeTest.SingleTaskActivity}
      Run #1: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

            可見,其中StandardCActivity被從堆棧中移除,其生命週期爲:

11-28 04:13:09.295 2163-2163/base.example.com I/StandardCActivity: onPause: 
11-28 04:13:09.311 2163-2163/base.example.com I/SingleTaskActivity: onNewIntent: 
11-28 04:13:09.311 2163-2163/base.example.com I/SingleTaskActivity: onStart: 
11-28 04:13:09.311 2163-2163/base.example.com I/SingleTaskActivity: onResume: 
11-28 04:13:09.343 2163-2163/base.example.com W/EGL_genymotion: eglSurfaceAttrib not implemented
11-28 04:13:09.719 2163-2163/base.example.com I/StandardCActivity: onStop: 
11-28 04:13:09.719 2163-2163/base.example.com I/StandardCActivity: onDestroy:

        可見,直接將SingleTaskActivity上面的StandardCActivity移除,並調用了本身的onNewIntent()方法StandardCActivity本身走了本身的destroy流程。(棧內複用)

            1.2.1 使用taskAffinity屬性

                    taskAffinity屬性能夠翻譯爲任務相關性,主要表示的是此Activity的進程名字(默認進程是包名)。其中的值必須爲字符串,而且包含「.」

                    例如以下定義:

<activity android:name=".launchmodeTest.SingleTaskWithAffinityActivity"
            android:launchMode="singleTask" android:taskAffinity="com.cxy.test"></activity>

                    啓動後的棧爲:StandardAActivity-->SingleTaskWithAffinityActivity

Running activities (most recent first):
    TaskRecord{528e7e2c #12 A com.cxy.test U 0}
      Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity}
    TaskRecord{528c7a48 #11 A base.example.com U 0}
      Run #1: ActivityRecord{5276bcd4 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                    再啓動一個standard模式的Activity:StandardAActivity-->SingleTaskWithAffinityActivity-->StandardCActivity

Running activities (most recent first):
    TaskRecord{528e7e2c #12 A com.cxy.test U 0}
      Run #3: ActivityRecord{52889940 u0 base.example.com/.launchmodeTest.StandardCActivity}
      Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity}
    TaskRecord{528c7a48 #11 A base.example.com U 0}
      Run #1: ActivityRecord{5276bcd4 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                               能夠查看出來,誰啓動的Activity,就會在誰的棧中添加對應的Activity。除非被啓動的Activity已經制定了進程名

                    再次啓動SingleTaskWithAffinityActivity:StandardAActivity-->SingleTaskWithAffinityActivity-->SingleTaskWithAffinityActivity

Running activities (most recent first):
    TaskRecord{528e7e2c #12 A com.cxy.test U 0}
      Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity}
    TaskRecord{528c7a48 #11 A base.example.com U 0}
      Run #1: ActivityRecord{5276bcd4 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                    生命週期:

11-28 04:37:02.595 2411-2411/base.example.com I/StandardCActivity: onPause: 
11-28 04:37:02.607 2411-2411/base.example.com I/SingleTaskWithAffinityA: onNewIntent: 
11-28 04:37:02.607 2411-2411/base.example.com I/SingleTaskWithAffinityA: onStart: 
11-28 04:37:02.611 2411-2411/base.example.com I/SingleTaskWithAffinityA: onResume: 
11-28 04:37:02.647 2411-2411/base.example.com W/EGL_genymotion: eglSurfaceAttrib not implemented
11-28 04:37:03.019 2411-2411/base.example.com I/StandardCActivity: onStop: 
11-28 04:37:03.019 2411-2411/base.example.com I/StandardCActivity: onDestroy:

                                可見調用了SingleTaskWithAffinityActivity的onNewIntent()、onStart()、onResume()方法。並將StandardCActivity從堆棧中移除了。

                    再次啓動SingleTaskActivity:StandardAActivity-->SingleTaskWithAffinityActivity-->StandardCActivity-->SingleTaskActivity

Running activities (most recent first):
    TaskRecord{528321b0 #13 A base.example.com U 0}
      Run #4: ActivityRecord{5292dca8 u0 base.example.com/.launchmodeTest.SingleTaskActivity}
    TaskRecord{5288a210 #14 A com.cxy.test U 0}
      Run #3: ActivityRecord{528ddc64 u0 base.example.com/.launchmodeTest.StandardCActivity}
      Run #2: ActivityRecord{5288e658 u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity}
    TaskRecord{528321b0 #13 A base.example.com U 0}
      Run #1: ActivityRecord{52889940 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                                可見設置了singleTask模式的activity,會在原來的堆棧中

                    假設給standard模式的activity設置taskAffinity屬性

<activity
            android:name=".launchmodeTest.StandardCActivity"
            android:label="C"
            android:taskAffinity="com.cxy.test.one"/>

                            啓動的結果爲:StandardAActivity-->SingleTaskWithAffinityActivity-->StandardCActivity

Running activities (most recent first):
    TaskRecord{5276b448 #16 A com.cxy.test U 0}
      Run #3: ActivityRecord{5288e658 u0 base.example.com/.launchmodeTest.StandardCActivity}
      Run #2: ActivityRecord{528ddc64 u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity}
    TaskRecord{528d42c4 #15 A base.example.com U 0}
      Run #1: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                            taskAffinity必須與singleTask模式使用,纔會有效果。(書上說的,須要本身去驗證)

        1.3  singleInstance單實例模式

               如下涉及到的activity的定義:

<activity
            android:name=".launchmodeTest.StandardAActivity"
            android:label="A">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".launchmodeTest.SingleTopActivity"
            android:label="棧頂複用"
            android:launchMode="singleTop" />
        <activity
            android:name=".launchmodeTest.SingleTaskActivity"
            android:label="棧內複用"
            android:launchMode="singleTask" />
        <activity
            android:name=".launchmodeTest.SingleInstanceActivity"
            android:label="單獨的一個棧"
            android:launchMode="singleInstance" />
        <activity
            android:name=".launchmodeTest.StandardCActivity"
            android:label="C"/>
        <activity android:name=".launchmodeTest.SingleTaskWithAffinityActivity"
            android:launchMode="singleTask" android:taskAffinity="com.cxy.test"></activity>

               1.3.1 在普通Activity跳轉到singleInstance的Activity

                            StandardAActivity-->SingleInstanceActivity

Running activities (most recent first):
    TaskRecord{52885efc #18 A base.example.com U 0}
      Run #2: ActivityRecord{52937648 u0 base.example.com/.launchmodeTest.SingleInstanceActivity}
    TaskRecord{52897aa0 #17 A base.example.com U 0}
      Run #1: ActivityRecord{528a6334 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                            直接新啓動了一個編號爲18的任務棧來單獨存放,並做爲前臺任務棧

                        1.3.1.1 在singleInstance的Activity跳轉到普通Activity

                                         StandardAActivity-->SingleInstanceActivity-->StandardCActivity

Running activities (most recent first):
    TaskRecord{52897aa0 #17 A base.example.com U 0}
      Run #3: ActivityRecord{52905030 u0 base.example.com/.launchmodeTest.StandardCActivity}
    TaskRecord{52885efc #18 A base.example.com U 0}
      Run #2: ActivityRecord{52937648 u0 base.example.com/.launchmodeTest.SingleInstanceActivity}
    TaskRecord{52897aa0 #17 A base.example.com U 0}
      Run #1: ActivityRecord{528a6334 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                        1.3.1.2 點擊返回按鈕

Running activities (most recent first):
    TaskRecord{52897aa0 #17 A base.example.com U 0}
      Run #2: ActivityRecord{528a6334 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{52885efc #18 A base.example.com U 0}
      Run #1: ActivityRecord{52937648 u0 base.example.com/.launchmodeTest.SingleInstanceActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                         1.3.1.2 點擊返回按鈕

Running activities (most recent first):
    TaskRecord{52885efc #18 A base.example.com U 0}
      Run #1: ActivityRecord{52937648 u0 base.example.com/.launchmodeTest.SingleInstanceActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

               1.3.2 在singleInstance的Activity跳轉到SingleTop的Activity

                            StandardAActivity-->SingleInstanceActivity-->SingleTopActivity

Running activities (most recent first):
    TaskRecord{528864b0 #21 A base.example.com U 0}
      Run #3: ActivityRecord{5288e658 u0 base.example.com/.launchmodeTest.SingleTopActivity}
    TaskRecord{5289313c #22 A base.example.com U 0}
      Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleInstanceActivity}
    TaskRecord{528864b0 #21 A base.example.com U 0}
      Run #1: ActivityRecord{5276bcd4 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

               1.3.3 在singleInstance的Activity跳轉到SingleTask的Activity

                            StandardAActivity-->SingleInstanceActivity-->SingleTaskActivity

Running activities (most recent first):
    TaskRecord{52863e64 #23 A base.example.com U 0}
      Run #3: ActivityRecord{528acda4 u0 base.example.com/.launchmodeTest.SingleTaskActivity}
    TaskRecord{52830620 #24 A base.example.com U 0}
      Run #2: ActivityRecord{528aaa88 u0 base.example.com/.launchmodeTest.SingleInstanceActivity}
    TaskRecord{52863e64 #23 A base.example.com U 0}
      Run #1: ActivityRecord{528aa754 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

               1.3.4 在singleInstance的Activity跳轉到SingleTask+AffinityActivity

                            StandardAActivity-->SingleInstanceActivity-->SingleTaskWithAffinityActivity

Running activities (most recent first):
    TaskRecord{528cbc48 #27 A com.cxy.test U 0}
      Run #3: ActivityRecord{5288e658 u0 base.example.com/.launchmodeTest.SingleTaskWithAffinityActivity}
    TaskRecord{52832ec8 #26 A base.example.com U 0}
      Run #2: ActivityRecord{527919fc u0 base.example.com/.launchmodeTest.SingleInstanceActivity}
    TaskRecord{528c7cc0 #25 A base.example.com U 0}
      Run #1: ActivityRecord{5276bcd4 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

               1.3.5 在singleInstance的Activity跳轉到 singleInstance的Activity

                            StandardAActivity-->SingleInstanceActivity-->SingleInstanceActivity

Running activities (most recent first):
    TaskRecord{528009a8 #29 A base.example.com U 0}
      Run #2: ActivityRecord{528acda4 u0 base.example.com/.launchmodeTest.SingleInstanceActivity}
    TaskRecord{528ac1bc #28 A base.example.com U 0}
      Run #1: ActivityRecord{528aa754 u0 base.example.com/.launchmodeTest.StandardAActivity}
    TaskRecord{528c8b7c #2 A com.android.launcher U 0}
      Run #0: ActivityRecord{528aca90 u0 com.android.launcher/com.android.launcher2.Launcher}

                            對應的生命週期爲:

11-28 08:07:00.135 3369-3369/base.example.com I/SingleInstanceActivity: onPause: 
11-28 08:07:00.135 3369-3369/base.example.com I/SingleInstanceActivity: onNewIntent: 
11-28 08:07:00.135 3369-3369/base.example.com I/SingleInstanceActivity: onResume:

                        總結:singleInstance的Activity只會單獨存放在一個堆棧中。而且對此啓動都不會再次建立,只會調用onNewIntent相關的生命週期方法

二、設置intent的Flag屬性

    FLAG_ACTIVITY_NEW_TASK:使用一個新的task來啓動Activity。一般使用在service中啓動Activity
    FLAG_ACTIVITY_SINGLE_TOP:使用singleTop模式來啓動Activity
    FLAG_ACTIVITY_CLEAR_TOP:使用singleTask模式來啓動Activity
    FLAG_ACTIVITY_NO_HISTORY:使用此模式啓動的Activity,該Activity啓動完其餘Activity之後,此Activity會從棧中消失

    還有一些其餘的屬性,須要本身去試一下。

注意:

(1)、在優先級上:以上兩種啓動模式,設置intent的flag屬性的優先級會更高。

(2)、在限定範圍上,設置android:launchMode屬性這種方式,沒法爲Activity設定FLAG_ACTIVITY_CLEAR_TOP標誌。

        設置intent的Flag屬性的方式,沒法指定singleInstance的方式。

(3)、非特殊狀況,儘可能使用設置android:launchMode屬性這種方式

相關文章
相關標籤/搜索