activity的启动模式

284 阅读21分钟

[TOC]

在Android中Activity的启动模式是可以自己定义的,可以通过两种方法进行自定义:

  • 1.使用清单文件定义:在AndroidManifest中定义Activity元素时用元素的 launchMode属性定义启动模式。
  • 2.使用Intent标志定义:在调用startActivity()时,可以在Intent中加入一个标志,用于声明启动模式。

1.使用清单文件定义

在使用清单定义时,可以定义四种启动模式如下: standard(默认模式)、singleTop、singleTask、singleInstance 使用例子如下:

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

如果没有设置==android:launchMode== 默认为standard(默认模式)模式。

1.standard模式(默认模式)

这个模式是默认模式,系统在启动这个模式的Activity的任务中每次都会创建一个新的实例并向其传送Intent。Activity可以多次实例化,而且每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。 如下图所示:

  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都会重新创建一个新的实例。

2.SingleTop模式(栈顶复用)

这个模式是在当前堆栈的顶部已经存在Activity的一个实例了,则系统在启动这个activity时,系统不会重新去创建一个新的实例,而是直接调用堆栈顶部的onNewIntent()返回向其传送Intent。 在这个模式下 Activity可以多次实例化,而且每个实例均可以属于不同的任务栈,并且一个任务栈都可以拥有多个实例(但是前提是位于栈顶的Activity并不是该Activity的现有实例)。

如下图所示:

  1. 从MainActivity启动SingleTopActivity,系统会创建一个SingleTopActivity的实例存入堆栈的顶部,并展示给用户。
  2. 在SingleTopActivity的实例中启动SingleTopActivity,这时由于栈顶的顶部是SingleTopActivity的实例,所以系统不会去重新创建一个实例,而是直接调用 ==onNewIntent()== 方法并传入Intent。
  3. 在SingleTopActivity的实例中启动OtherTopActivity,这是系统会创建一个OtherTopActivity的实例存入堆栈的顶部,并展示给用户。
  4. 在OtherTopActivity的实例中启动SingleTopActivity,这是由于栈顶不是SingleTopActivity的实例,所以系统会重新创建一个SingleTopActivity的实例存入栈顶,并展示给用户,而不是直接调用堆栈中的SingleTopActivity实例的onNewIntent()方法。
  5. 用户点击返回时堆栈会从栈顶一个一个的移出并销毁。

下面是日志:

 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模式下

  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之后没有出现那个一启动就回调的问题。

注意:如果你在开发关于这个的问题记得向下兼容。

这个例子的代码在这里