activity的啓動模式

[TOC]html

在Android中Activity的啓動模式是能夠本身定義的,能夠經過兩種方法進行自定義:java

  • 1.使用清單文件定義:在AndroidManifest中定義Activity元素時用元素的 launchMode屬性定義啓動模式。
  • 2.使用Intent標誌定義:在調用startActivity()時,能夠在Intent中加入一個標誌,用於聲明啓動模式。

1.使用清單文件定義

在使用清單定義時,能夠定義四種啓動模式以下: standard(默認模式)、singleTop、singleTask、singleInstance 使用例子以下:android

<activity android:name=".standard.StandardActivity" android:launchMode="standard"/>

複製代碼

若是沒有設置==android:launchMode== 默認爲standard(默認模式)模式。git

1.standard模式(默認模式)

這個模式是默認模式,系統在啓動這個模式的Activity的任務中每次都會建立一個新的實例並向其傳送Intent。Activity能夠屢次實例化,並且每一個實例都可屬於不一樣的任務,而且一個任務能夠擁有多個實例。 以下圖所示:github

  1. 在MainActivity中啓動一個StandardActivity,系統建立了一個實例並並存入棧中,這時 StandardActivity在堆棧頂部而且顯示給用戶。
  2. 在StandardActivity啓動一個StandardActivity時系統會在從新建立一個實例並存入堆棧頂部顯示給用戶,這時堆棧中有兩個StandardActivity的實例。
  3. 用戶點擊返回時堆棧頂部的第二個StandardActivity被移出堆棧並銷燬,這時第一個StandardActivity會在堆棧頂部並向用戶展現,用戶在點擊返回時會返回到MainActivity。 。 如下是運行時的日誌:
StandardActivity1 :onCreate 方法-------------------------
 StandardActivity1 :onCreate:StandardActivity  TaskId:143   TaskNum:2  hasCode:156403808
 StandardActivity1:TaskAffinity:com.hugo.reviewbasic
 StandardActivity1 :onStart 方法-------------------------
 StandardActivity1 :onResume 方法-------------------------
 MainActivity :onSaveInstanceState 方法-------------------------
 MainActivity :onStop 方法-------------------------
 StandardActivity1 :onPause 方法-------------------------
 StandardActivity2 :onCreate 方法-------------------------
 StandardActivity2 :onCreate:StandardActivity  TaskId:143   TaskNum:3  hasCode:15174462
 StandardActivity2:TaskAffinity:com.hugo.reviewbasic
 StandardActivity2 :onStart 方法-------------------------
 StandardActivity2 :onResume 方法-------------------------
 StandardActivity1 :onSaveInstanceState 方法-------------------------
 StandardActivity1 :onStop 方法-------------------------
 StandardActivity2 :onPause 方法-------------------------
 StandardActivity1 :onRestart 方法-------------------------
 StandardActivity1 :onStart 方法-------------------------
 StandardActivity1 :onResume 方法-------------------------
 StandardActivity2 :onStop 方法-------------------------
 StandardActivity2 :onDestroy 方法-------------------------
 StandardActivity1 :onPause 方法-------------------------
 MainActivity :onRestart 方法-------------------------
 MainActivity :onStart 方法-------------------------
 MainActivity :onResume 方法-------------------------
 StandardActivity1 :onStop 方法-------------------------
 StandardActivity1 :onDestroy 方法-------------------------
複製代碼

這裏咱們能夠看到standard啓動模式爲:每次啓動一個Activity都會從新建立一個新的實例。bash

2.SingleTop模式(棧頂複用)

這個模式是在當前堆棧的頂部已經存在Activity的一個實例了,則系統在啓動這個activity時,系統不會從新去建立一個新的實例,而是直接調用堆棧頂部的onNewIntent()返回向其傳送Intent。 在這個模式下 Activity能夠屢次實例化,並且每一個實例都可以屬於不一樣的任務棧,而且一個任務棧均可以擁有多個實例(可是前提是位於棧頂的Activity並非該Activity的現有實例)。app

以下圖所示:測試

  1. 從MainActivity啓動SingleTopActivity,系統會建立一個SingleTopActivity的實例存入堆棧的頂部,並展現給用戶。
  2. 在SingleTopActivity的實例中啓動SingleTopActivity,這時因爲棧頂的頂部是SingleTopActivity的實例,因此係統不會去從新建立一個實例,而是直接調用 ==onNewIntent()== 方法並傳入Intent。
  3. 在SingleTopActivity的實例中啓動OtherTopActivity,這是系統會建立一個OtherTopActivity的實例存入堆棧的頂部,並展現給用戶。
  4. 在OtherTopActivity的實例中啓動SingleTopActivity,這是因爲棧頂不是SingleTopActivity的實例,因此係統會從新建立一個SingleTopActivity的實例存入棧頂,並展現給用戶,而不是直接調用堆棧中的SingleTopActivity實例的onNewIntent()方法。
  5. 用戶點擊返回時堆棧會從棧頂一個一個的移出並銷燬。

下面是日誌:this

MainActivity :onPause 方法-------------------------
 SingleTopActivity :onCreate 方法-------------------------
 SingleTopActivity :onCreate:SingleTopActivity  TaskId:145   TaskNum:2  hasCode:156403808
 SingleTopActivity:TaskAffinity:com.hugo.reviewbasic
 SingleTopActivity :onStart 方法-------------------------
 SingleTopActivity :onResume 方法-------------------------
 MainActivity :onSaveInstanceState 方法-------------------------
 MainActivity :onStop 方法-------------------------
 SingleTopActivity :onPause 方法-------------------------
 SingleTopActivity :onNewIntent 方法-------------------------
 SingleTopActivity :onNewIntent:SingleTopActivity  TaskId:145   TaskNum:2  hasCode:156403808
 SingleTopActivity:TaskAffinity:com.hugo.reviewbasic
 SingleTopActivity :onResume 方法-------------------------
 SingleTopActivity :onPause 方法-------------------------
 OtherTopActiivty :onCreate 方法-------------------------
 OtherTopActiivty :onCreate:OtherTopActiivty  TaskId:145   TaskNum:3  hasCode:135228666
 OtherTopActiivty:TaskAffinity:com.hugo.reviewbasic
 OtherTopActiivty :onStart 方法-------------------------
 OtherTopActiivty :onResume 方法-------------------------
 SingleTopActivity :onSaveInstanceState 方法-------------------------
 SingleTopActivity :onStop 方法-------------------------
 OtherTopActiivty :onPause 方法-------------------------
 SingleTopActivity :onCreate 方法-------------------------
 SingleTopActivity :onCreate:SingleTopActivity  TaskId:145   TaskNum:4  hasCode:204001128
 SingleTopActivity:TaskAffinity:com.hugo.reviewbasic
 SingleTopActivity :onStart 方法-------------------------
 SingleTopActivity :onResume 方法-------------------------
 OtherTopActiivty :onSaveInstanceState 方法-------------------------
 OtherTopActiivty :onStop 方法-------------------------
 SingleTopActivity :onPause 方法-------------------------
 OtherTopActiivty :onRestart 方法-------------------------
 OtherTopActiivty :onStart 方法-------------------------
 OtherTopActiivty :onResume 方法-------------------------
 SingleTopActivity :onStop 方法-------------------------
 SingleTopActivity :onDestroy 方法-------------------------
 OtherTopActiivty :onPause 方法-------------------------
 SingleTopActivity :onRestart 方法-------------------------
 SingleTopActivity :onStart 方法-------------------------
 SingleTopActivity :onResume 方法-------------------------
 OtherTopActiivty :onStop 方法-------------------------
 OtherTopActiivty :onDestroy 方法-------------------------
 SingleTopActivity :onPause 方法-------------------------
 MainActivity :onRestart 方法-------------------------
 MainActivity :onStart 方法-------------------------
 MainActivity :onResume 方法-------------------------
 SingleTopActivity :onStop 方法-------------------------
 SingleTopActivity :onDestroy 方法-------------------------
複製代碼

咱們能夠看到在SingleTop模式下spa

  1. 當前堆棧中已經有了該Activity的實例而且該實例位於堆棧頂部時,啓動該Activity不會從新建立實例,而是複用該Activity在棧頂的實例,調用onNewIntent()方法傳入Intent。
  2. 當前堆棧中已經有了該Activity的實例可是該實例不在堆棧頂部時,啓動該Activity其行爲和standard啓動模式是同樣的,會從新建立一個新的實例。
  3. 當前堆棧中沒有該Activity的實例時,啓動該Activity的行爲和Standard啓動模式同樣。

3.singleTask模式(棧內複用模式)

在這個模式下啓動Activity時,若是棧中存在這個Activity的實例就會複用這個實例,無論它是否位於任務棧頂,複用時,會將它之上的全部其餘Activity的實例移動任務棧,而且調用該實例的onNewIntent()方法傳入Intent。其實在這個過程當中還存在一個任務棧的匹配,由於這個模式啓動時,會在本身須要的任務棧中尋找實例,這個任務棧是經過taskAffinity屬性指定的,若是任務棧不存在,則會建立這個任務棧。

任務棧在Androidmanifest 文件聲明Activity是設置 若是沒有設置默認爲軟件包名

任務棧設置以下:

<activity android:name=".singleTask.OtherSingleTaskActivity" android:launchMode="singleTask" android:taskAffinity="com.hugo.OtherSingleTaskActivity" />
複製代碼

例子步驟以下圖:

  1. 在MainActivity中SingleTask模式啓動SingleTaskActivity,因爲棧類沒有該Activity實例,而且該Activity聲明時沒有設置任務棧,因此係統建立了一個實例並存入默認任務棧頂部。
  2. 在SingleTaskActivity中啓動一個OtherActivity,OtherActivity爲默認啓動模式,因此係統建立一個實例並存入默認task中。
  3. 在OtherActivity中SingleTask模式啓動OtherSingleTaskActivity,因爲OtherSingleTaskActivity在聲明時設置了任務棧,這時該任務棧並無建立,因此係統會建立新的任務棧並建立OtherSingleTaskActivity存入新的任務棧,而後這個新任務棧會存入back stack(回退棧)頂部。
  4. 在OtherSingleTaskActivity的實例中默認模式啓動一個OtherActivity,系統會建立一個新的實例並存入新任務棧頂部。
  5. 在新任務棧的OtherActivity實例中啓動SingleTaskActivity,因爲SingleTaskActivity實例已經存在,因此係統會匹配對應的任務棧(默認任務棧),並找到SingleTaskActivity的實例,調用該實例的onNewIntent()方法傳入Intent,並把該任務棧(默認任務棧)移到回退棧的頂部,而任務棧中在該實例之上的Activity實例會被移出任務棧並銷燬,而讓該實例顯示給用戶。
  6. 點擊返回,會把SingleTaskActivity實例移出默認任務棧並銷燬,使MainActivity實例顯示給用戶。
  7. 再次點擊返回,會把MainActivity實例移出默認任務棧並銷燬,這是默認任務棧已經沒有Activity實例了,因此會把新的任務棧中的頂部OtherActivity的實例顯示給用戶。
  8. 再次點擊返回,會把新任務中的OtherActivity的實例移出任務棧並銷燬,把任務棧中的OtherSingleTaskActivity的實例展現給用戶。
  9. 再次點擊返回,這時會把任務棧中OtherSingleTaskActivity的實例移出任務棧,並退出APP返回桌面。

以上步驟日誌以下:

MainActivity :onPause 方法--------------------  hasCode:26596009
 SingleTaskActivity :onCreate 方法-------------------------
 SingleTaskActivity :onCreate:SingleTaskActivity  hasCode:236910323  TaskId:166   TaskNum:2   TaskAffinity:com.hugo.reviewbasic
 SingleTaskActivity :onStart 方法------------------  hasCode:236910323
 SingleTaskActivity :onResume 方法--------------------  hasCode:236910323
 MainActivity :onSaveInstanceState 方法------------------  hasCode:26596009
 MainActivity :onStop 方法-------------------  hasCode:26596009
 SingleTaskActivity :onPause 方法--------------------  hasCode:236910323
 OtherActivity :onCreate 方法-------------------------
 OtherActivity :onCreate:OtherActivity  hasCode:162823661  TaskId:166   TaskNum:3   TaskAffinity:com.hugo.reviewbasic
 OtherActivity :onStart 方法------------------  hasCode:162823661
 OtherActivity :onResume 方法--------------------  hasCode:162823661
 SingleTaskActivity :onSaveInstanceState 方法------------------  hasCode:236910323
 SingleTaskActivity :onStop 方法-------------------  hasCode:236910323
 OtherActivity :onPause 方法--------------------  hasCode:162823661
 OtherSingleTaskActivity :onCreate 方法-------------------------
 OtherSingleTaskActivity :onCreate:OtherSingleTaskActivity  hasCode:182738289  TaskId:167   TaskNum:1   TaskAffinity:com.hugo.OtherSingleTaskActivity
 OtherSingleTaskActivity :onStart 方法------------------  hasCode:182738289
 OtherSingleTaskActivity :onResume 方法--------------------  hasCode:182738289
 OtherActivity :onSaveInstanceState 方法------------------  hasCode:162823661
 OtherActivity :onStop 方法-------------------  hasCode:162823661
 OtherSingleTaskActivity :onPause 方法--------------------  hasCode:182738289
 OtherActivity :onCreate 方法-------------------------
 OtherActivity :onCreate:OtherActivity  hasCode:123068584  TaskId:167   TaskNum:2   TaskAffinity:com.hugo.reviewbasic
 OtherActivity :onStart 方法------------------  hasCode:123068584
 OtherActivity :onResume 方法--------------------  hasCode:123068584
 OtherSingleTaskActivity :onSaveInstanceState 方法------------------  hasCode:182738289
 OtherSingleTaskActivity :onStop 方法-------------------  hasCode:182738289
 OtherActivity :onDestroy 方法-------------------  hasCode:162823661
 OtherActivity :onPause 方法--------------------  hasCode:123068584
 SingleTaskActivity :onNewIntent 方法--------------------  hasCode:236910323
 SingleTaskActivity :onNewIntent:SingleTaskActivity  hasCode:236910323  TaskId:166   TaskNum:2   TaskAffinity:com.hugo.reviewbasic
 SingleTaskActivity :onRestart 方法-------------------  hasCode:236910323
 SingleTaskActivity :onStart 方法------------------  hasCode:236910323
 SingleTaskActivity :onResume 方法--------------------  hasCode:236910323
 OtherActivity :onSaveInstanceState 方法------------------  hasCode:123068584
 OtherActivity :onStop 方法-------------------  hasCode:123068584
 SingleTaskActivity :onPause 方法--------------------  hasCode:236910323
 MainActivity :onRestart 方法-------------------  hasCode:26596009
 MainActivity :onStart 方法------------------  hasCode:26596009
 MainActivity :onResume 方法--------------------  hasCode:26596009
 SingleTaskActivity :onStop 方法-------------------  hasCode:236910323
 SingleTaskActivity :onDestroy 方法-------------------  hasCode:236910323
 MainActivity :onPause 方法--------------------  hasCode:26596009
 OtherActivity :onRestart 方法-------------------  hasCode:123068584
 OtherActivity :onStart 方法------------------  hasCode:123068584
 OtherActivity :onResume 方法--------------------  hasCode:123068584
 MainActivity :onStop 方法-------------------  hasCode:26596009
 MainActivity :onDestroy 方法-------------------  hasCode:26596009
 OtherActivity :onPause 方法--------------------  hasCode:123068584
 OtherSingleTaskActivity :onRestart 方法-------------------  hasCode:182738289
 OtherSingleTaskActivity :onStart 方法------------------  hasCode:182738289
 OtherSingleTaskActivity :onResume 方法--------------------  hasCode:182738289
 OtherActivity :onStop 方法-------------------  hasCode:123068584
 OtherActivity :onDestroy 方法-------------------  hasCode:123068584
 OtherSingleTaskActivity :onPause 方法--------------------  hasCode:182738289
 OtherSingleTaskActivity :onStop 方法-------------------  hasCode:182738289
 OtherSingleTaskActivity :onDestroy 方法-------------------  hasCode:182738289
複製代碼

咱們能夠看到在SingleTask啓動模式下

  1. 啓動Activity時會根據taskffinity 去尋找當前是否存在一個對應名字的任務棧,
    • 若是存在,則獲得該任務棧,在查找任務棧中是否存在該Activity的實例,
      • 若是存在實例,就把該任務棧中在該Activity實例之上Activity實例都移出任務棧,而後調用該Activity實例的onNewIntent()返回傳入Intent。
      • 若是不存在,這新建Activity實例並存入任務棧中。
    • 若是不存在,則會建立一個新的任務棧,並建立新的Activity實例並存入新建的任務棧中。
  2. 若是咱們在兩個不一樣的APP中的Activity設置爲相同的TaskAffinity,這樣雖然在不一樣的應用中,可是Activity會被分配到同一個task中去。以下圖所示:

日誌

com.hugo.wanandroid I/OtherSingleTaskActivity: [hugo]  OtherSingleTaskActivity :onCreate:OtherSingleTaskActivity  hasCode:153472021  TaskId:210   TaskAffinity:com.hugo.OtherSingleTaskActivity

com.hugo.reviewbasic I/BaseActivity: [hugo]  OtherSingleTaskActivity :onCreate:OtherSingleTaskActivity  hasCode:97368138  TaskId:210   TaskNum:2   TaskAffinity:com.hugo.OtherSingleTaskActivity
複製代碼

咱們能夠在圖中看到ComponenApp中的一個Activity和個人測試App的OtherSingleTaskActivity 設置在了同一個任務棧 因此在我先打開ComponenApp的Activity按Home鍵回到桌面在在個人測試App打開OtherSingleTaskActivity 時不會從新建立一個新的任務棧而是獲取了ComponenApp啓動Activity時建立的任務棧(日誌中的==TaskId:210==),並把OtherSingleTaskActivity的實例存入這個任務棧,而後把整個任務移動到回退堆棧的頂部,這時咱們點返回後,顯示的不是SingleTaskActivity,而是ComponenApp中的Activity,在點擊返回時纔會返回到SingleTaskActivity,而這是ComponenApp中的Activity也已經被關閉並銷燬。

4.SingleInstance模式

這種模式與SingleTask模式基本同樣,只是系統不會將任何其餘的Activity啓動到包含實例的任務棧中,該Activity始終是其任務棧中惟一僅有的成員;由此Activity啓動的任何Activity均在其餘的任務棧中打開。

以下圖所示:

  1. 在MainActivity中SingleInstance模式啓動SingleInstanceActivity中standard模式啓動OtherActivity1,因爲SingleInstanceActivity沒有啓動過,因此係統會建立一個新的任務棧task1,而後建立該Activity的實例存入任務棧task1中,並把該任務棧task1存入到回退棧頂。
  2. 在SingleInstanceActivity因此中standard模式啓動OtherActivity1,因爲是在SingleInstanceActivity因此OtherActivity1的實例會被系統分配給別的任務棧,這裏是分配給了默認任務棧,並把默認任務棧移動到了回退棧的頂部。
  3. 在OtherActivity1的實例中用SingleInstance模式啓動OtherSingleInstanceActivity,因爲這是系統中沒有OtherSingleInstanceActivity的實例,因此係統會建立一個新的任務棧task2,而後把新建的該Activity的實例存入該任務棧,並把該任務棧移動存入回退棧頂。
  4. 在OtherSingleInstanceActivity的實例中用Standard模式啓動一個OtherActivity1,這時系統會把新建立的OtherActivity1的實例分配給其餘的任務棧,這裏是分配給了默認任務棧,並把任務棧移動到回退棧頂。
  5. 在OtherActivity1的實例中啓動SingleInstanceActivity,因爲SingleInstanceActivity的實例已經存在,全部這時系統會自動去匹配任務棧找到已經存在的實例,並把該任務棧移動到回退棧頂。
  6. 點擊返回,把SingleInstanceActivity的實例從task1任務棧移出並關閉該任務棧,這是在回退棧中默認任務棧到了回退棧頂,因此在默認任務棧頂的OtherActivity1的第二個實例顯示給用戶。
  7. 點擊返回,從默認任務棧中移出OtherActivity1的第二個實例並銷燬,這時因爲默認task是在回退棧頂的因此,當OtherActivity1的第二個實例移出棧後顯示在前臺的是OtherActivity1的第一個實例,而不是OtherSingleInstanceActivity。
  8. 點擊返回,這是會把OtherActivity1的第一個實例移出棧並銷燬,而後顯示MainActivity。
  9. 點擊返回,會把MainActivity移出棧,這是在默認的task中已經沒有了實例,因此默認的task也會被銷燬,而後顯示回退棧中處於頂部的task2任務棧中的OtherSingleInstanceActivity。
  10. 點擊返回會移出OtherSingleInstanceActivity實例並關閉task2任務棧。退出APP,返回桌面。

提示:若是咱們在第10步時用Standard模式啓動一個Activity,系統會從新建立一個新的task任務棧來存儲該Activity的實例。

下面是按照上面步驟的日誌:

MainActivity :onCreate 方法-------------------------
 MainActivity :onCreate:MainActivity  hasCode:53162219  TaskId:221   TaskNum:1   TaskAffinity:com.hugo.reviewbasic
 MainActivity :onStart 方法------------------  hasCode:53162219
 MainActivity :onResume 方法--------------------  hasCode:53162219
 MainActivity :onPause 方法--------------------  hasCode:53162219
 SingleInstanceActivity :onCreate 方法-------------------------
 SingleInstanceActivity :onCreate:SingleInstanceActivity  hasCode:35048165  TaskId:222   TaskNum:1   TaskAffinity:com.hugo.reviewbasic
 SingleInstanceActivity :onStart 方法------------------  hasCode:35048165
 SingleInstanceActivity :onResume 方法--------------------  hasCode:35048165
 MainActivity :onSaveInstanceState 方法------------------  hasCode:53162219
 MainActivity :onStop 方法-------------------  hasCode:53162219
 SingleInstanceActivity :onPause 方法--------------------  hasCode:35048165
 OtherActivity1 :onCreate 方法-------------------------
 OtherActivity1 :onCreate:OtherActivity1  hasCode:220012746  TaskId:221   TaskNum:2   TaskAffinity:com.hugo.reviewbasic
 OtherActivity1 :onStart 方法------------------  hasCode:220012746
 OtherActivity1 :onResume 方法--------------------  hasCode:220012746
 SingleInstanceActivity :onSaveInstanceState 方法------------------  hasCode:35048165
 SingleInstanceActivity :onStop 方法-------------------  hasCode:35048165
 OtherActivity1 :onPause 方法--------------------  hasCode:220012746
 OtherSingleInstanceActivity :onCreate 方法-------------------------
 OtherSingleInstanceActivity :onCreate:OtherSingleInstanceActivity  hasCode:245363070  TaskId:223   TaskNum:1   TaskAffinity:con.hugo.instance1
 OtherSingleInstanceActivity :onStart 方法------------------  hasCode:245363070
 OtherSingleInstanceActivity :onResume 方法--------------------  hasCode:245363070
 OtherActivity1 :onSaveInstanceState 方法------------------  hasCode:220012746
 OtherActivity1 :onStop 方法-------------------  hasCode:220012746
 OtherSingleInstanceActivity :onPause 方法--------------------  hasCode:245363070
 OtherActivity1 :onCreate 方法-------------------------
 OtherActivity1 :onCreate:OtherActivity1  hasCode:87192460  TaskId:221   TaskNum:3   TaskAffinity:com.hugo.reviewbasic
 OtherActivity1 :onStart 方法------------------  hasCode:87192460
 OtherActivity1 :onResume 方法--------------------  hasCode:87192460
 OtherSingleInstanceActivity :onSaveInstanceState 方法------------------  hasCode:245363070
 OtherSingleInstanceActivity :onStop 方法-------------------  hasCode:245363070
 OtherActivity1 :onPause 方法--------------------  hasCode:87192460
 SingleInstanceActivity :onNewIntent 方法--------------------  hasCode:35048165
 SingleInstanceActivity :onNewIntent:SingleInstanceActivity  hasCode:35048165  TaskId:222   TaskNum:1   TaskAffinity:com.hugo.reviewbasic
 SingleInstanceActivity :onRestart 方法-------------------  hasCode:35048165
 SingleInstanceActivity :onStart 方法------------------  hasCode:35048165
 SingleInstanceActivity :onResume 方法--------------------  hasCode:35048165
 OtherActivity1 :onSaveInstanceState 方法------------------  hasCode:87192460
 OtherActivity1 :onStop 方法-------------------  hasCode:87192460
 SingleInstanceActivity :onPause 方法--------------------  hasCode:35048165
 OtherActivity1 :onRestart 方法-------------------  hasCode:87192460
 OtherActivity1 :onStart 方法------------------  hasCode:87192460
 OtherActivity1 :onResume 方法--------------------  hasCode:87192460
 SingleInstanceActivity :onStop 方法-------------------  hasCode:35048165
 SingleInstanceActivity :onDestroy 方法-------------------  hasCode:35048165
 OtherActivity1 :onPause 方法--------------------  hasCode:87192460
 OtherActivity1 :onRestart 方法-------------------  hasCode:220012746
 OtherActivity1 :onStart 方法------------------  hasCode:220012746
 OtherActivity1 :onResume 方法--------------------  hasCode:220012746
 OtherActivity1 :onStop 方法-------------------  hasCode:87192460
 OtherActivity1 :onDestroy 方法-------------------  hasCode:87192460
 OtherActivity1 :onPause 方法--------------------  hasCode:220012746
 MainActivity :onRestart 方法-------------------  hasCode:53162219
 MainActivity :onStart 方法------------------  hasCode:53162219
 MainActivity :onResume 方法--------------------  hasCode:53162219
 OtherActivity1 :onStop 方法-------------------  hasCode:220012746
 OtherActivity1 :onDestroy 方法-------------------  hasCode:220012746
 MainActivity :onPause 方法--------------------  hasCode:53162219
 OtherSingleInstanceActivity :onRestart 方法-------------------  hasCode:245363070
 OtherSingleInstanceActivity :onStart 方法------------------  hasCode:245363070
 OtherSingleInstanceActivity :onResume 方法--------------------  hasCode:245363070
 MainActivity :onStop 方法-------------------  hasCode:53162219
 MainActivity :onDestroy 方法-------------------  hasCode:53162219
 OtherSingleInstanceActivity :onPause 方法--------------------  hasCode:245363070
 OtherSingleInstanceActivity :onStop 方法-------------------  hasCode:245363070
 OtherSingleInstanceActivity :onDestroy 方法-------------------  hasCode:245363070
複製代碼

能夠看出SingleInstance啓動模式基本和SingleTask一致,區別就是SingleInstance的棧類只能存在一個自己實例,不能存在其餘Activity的實例,而SingleTask的棧內能夠存在其餘Activity的實例。

下面是官方的說明:

用例 啓動模式 多個實例? 註釋
大多數 Activity 的正常啓動 standard 默認值。系統始終會在目標任務中建立新的 Activity 實例並向其傳送 Intent。
singleTop 有條件 若是目標任務的頂部已存在一個 Activity 實例,則系統會經過調用該實例的 onNewIntent() 方法向其傳送 Intent,而不是建立新的 Activity 實例。
專用啓動
(不建議用做常規用途)
singleTask 系統在新任務的根位置建立 Activity 並向其傳送 Intent。 不過,若是已存在一個 Activity 實例,則系統會經過調用該實例的 onNewIntent() 方法向其傳送 Intent,而不是建立新的 Activity 實例。
singleInstance 與「singleTask"」相同,只是系統不會將任何其餘 Activity 啓動到包含實例的任務中。 該 Activity 始終是其任務惟一僅有的成員。

2.使用Intent標誌

使用Intent標誌返回設置啓動模式能夠是用多種標誌本文只簡介其中比較長用的幾種,想知道更多請點擊 這個連接 查看。

使用例子以下:

val intent =Intent(this,SingleInstanceActivity::class.java)
  intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
  startActivity(intent)

複製代碼

1. FLAG_ACTIVITY_NEW_TASK

在新任務中啓動Activity。若是該Activity已經啓動,則該Activity所在的任務轉到前臺並恢復其最後狀態,同時調用 ==onNewIntent()== 返回傳入Intent。

這個標誌會和前文中 清單設置launchMode 的「SingleTask」 的行爲相同。

2. FLAG_ACTIVITY_SINGLE_TOP

若是正在啓動的Activity是當前Activity(位於返回棧的頂部),則回調現有實例調用 ==onNewIntent()== 方法傳入Intent,而不會建立新的實例。

這個標誌和前文中 清單設置launchMode 的 「SingleTop」 的行爲相同。

3. FLAG_ACTIVITY_CLEAR_TOP

若是正在啓動的Activity已在當前任務中運行,則會銷燬當前任務頂部的全部Activity,並經過 onNewIntent() 返回鍵Intent傳遞給該Activity的實例(如今位於頂部),而不是啓動該Activity的新實例。

若是該Activity在其餘任務棧中已有實例或沒有實例,可是在當前任務棧中沒有,那麼系統會從新建立一個實例存入當前任務棧中。

若是啓動的Activity 的啓動模式爲「Standard」,則該Activity也會從堆棧中移除銷燬,並在其位置從新建立一個新實例,以便處理傳入的Intent。這是由於當啓動模式爲「Standard」時,將始終爲新Intent建立新實例。

3.關於關聯的配置(taskAffinity)

「關聯」是用於指示Activity優先屬於那個任務棧,默認狀況下,同一應用中的全部Activity彼此關聯。所以,默認狀況下,同一應用中的全部Activity優先位於相同任務中。不過能夠修改Activity的默認關聯。在不一樣應用中定義的Activity能夠共享關聯,或者能夠在同一個應用中定義的Activity分配不一樣的任務關聯。

設置以下:

<activity android:name=".singleInstance.OtherSingleInstanceActivity" android:launchMode="singleInstance" android:taskAffinity="con.hugo.instance1"/>
複製代碼
  1. 系統的默認關聯爲應用包名。
  2. 咱們能夠單獨爲每個Activity指定關聯。
  3. 在概念上,具備相同關聯的Activity(即設置了相同taskAffinity屬性的Activity)屬於同一個任務。
  4. 爲一個Activity的taskAffinity設置爲空字符串,表面這個Activity不屬於任何task。

4.啓動關於5.0如下startActivityForResult()的問題

在Android5.0之前使用startActivityForResult() 啓動 SingleTask 和SingleInstance 模式的Activity 會出現 一啓動就在onActivityResult()方法中收到回調的問題 日誌以下:

MainActivity :onPause 方法--------------------  hasCode:-1660511584
 MainActivity :onActivityResult 獲取數據:null   requestCode:10001
 MainActivity :onResume 方法--------------------  hasCode:-1660511584
 MainActivity :onPause 方法--------------------  hasCode:-1660511584
 SingleTaskActivity :onCreate 方法-------------------------
 SingleTaskActivity :onCreate:SingleTaskActivity  hasCode:-1659844560  TaskId:9   TaskNum:-1   TaskAffinity:com.hugo.reviewbasic
 SingleTaskActivity :onStart 方法------------------  hasCode:-1659844560
 SingleTaskActivity :onResume 方法--------------------  hasCode:-1659844560
 MainActivity :onSaveInstanceState 方法------------------  hasCode:-1660511584
 MainActivity :onStop 方法-------------------  hasCode:-1660511584
複製代碼

能夠看到在新的SingleTaskActivity還沒建立以前MainActivity就已經收到了回調並獲取焦點而後立刻又失去焦點。而後SingleTaskActivity才建立。

在5.0之後(包含)就不會出現這個狀況了

日誌以下:

MainActivity :onPause 方法--------------------  hasCode:56699745
 SingleInstanceActivity :onCreate 方法-------------------------
 SingleInstanceActivity :onCreate:SingleInstanceActivity  hasCode:156403808  TaskId:249   TaskNum:2   TaskAffinity:com.hugo.aaaaaaaaaaa
 SingleInstanceActivity :onStart 方法------------------  hasCode:156403808
 SingleInstanceActivity :onResume 方法--------------------  hasCode:156403808
 MainActivity :onSaveInstanceState 方法------------------  hasCode:56699745
 MainActivity :onStop 方法-------------------  hasCode:56699745
 MainActivity :onRestart 方法-------------------  hasCode:56699745
 MainActivity :onStart 方法------------------  hasCode:56699745
 MainActivity :onActivityResult 獲取數據:null   requestCode:10002
 MainActivity :onResume 方法--------------------  hasCode:56699745
 MainActivity :onPause 方法--------------------  hasCode:56699745
 MainActivity :onStop 方法-------------------  hasCode:56699745
 MainActivity :onDestroy 方法-------------------  hasCode:56699745
 SingleInstanceActivity :onStop 方法-------------------  hasCode:156403808
 SingleInstanceActivity :onDestroy 方法-------------------  hasCode:156403808
複製代碼

能夠看到在5.0之後是能夠正常返回的。==可是啓動模式已經失去了作用==。SingleInstance啓動模式下的Activity所在任務棧只能有惟一一個該Activity的實例,可是在日誌中咱們看到在這個任務棧中有2個實例。因此咱們能夠肯定在Android5.0以後爲了保證回調的功能,若是是startActivityForResult()啓動的Activity,那麼不論是設置的SingleTask仍是SingleInstance都不會去建立新的任務棧,而是建立實例存入該任務棧中。因此在5.0以後沒有出現那個一啓動就回調的問題。

注意:若是你在開發關於這個的問題記得向下兼容。

這個例子的代碼在這裏

相關文章
相關標籤/搜索