在AndroidManifest.xml中配置activity时,android:launchMode属性会指定启动activity的模式,有四种:

standard

singleTop

singleTask

singleInstance

这四种模式一般配合Intent属性变量FLAG_ACTIVITY_XXX使用,比如FLAG_ACTIVITY_NEW_TASK,本文暂时撇开FLAG_ACTIVITY_XXX,只讨论这四种模式的启动结果,先考虑只在同一个应用下的情况。

standard模式

系统默认情况下就是standard模式,假如A中设置为默认模式,A中有一个按钮,单击按钮时只启动自己,看看启动后的结果。AndroidManifest.xml、A和源码及布局分别为:

AndroidManifest.xml
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.administrator.myapplication">
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name="com.example.administrator.myapplication.AActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="com.feeyan.www.a_activity"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
            </intent-filter>
        </activity>
    </application>
 
</manifest>
AActivity.java
 
1
2
3
4
5
6
7
8
9
10
11
12
public class AActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.a_layout);
    }
 
    public void startToB(View view) {
        startActivity(new Intent("com.feeyan.www.a_activity"));
    }
}
a_layout.xml
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.administrator.myapplication.AActivity">
 
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
 
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="to B"
        android:id="@+id/button"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:textSize="20sp"
        android:onClick="startToB" />
</RelativeLayout>

注:本文案例在小米4上测试

假设现在没有运行程序,先通过命令dumpsys activity activities在串口中查看所有activity栈信息:

看红色区域,activity栈中只有一个代号为0的栈,栈中也只有一个id号为#1的task和id号为#0的ActivityRecord,ActivityRecord中保存的包名是com.miui.home,启动类名为.launcher.Launcher,也就是说,目前Activity栈中只有Launcher应用,没有别的应用。

现在启动案例,启动后的栈信息:

案例启动后,系统新建了一个栈stack #1,其中有新启动的Activity实例AActivity,保存在id号为#24的task中

然后,点击按钮再次启动AActivity,启动后的栈信息为:

在同样的stack #1、同样的task #24中多了一个AActicity实例,两个实例对应的ActivityRecord地址不一样,一个是42e23ae0,一个是42da3a08。

默认标准模式,每启动一次,就创建一个新实例,并放到栈顶,并且该实例放在同样的任务task中、同样的activity栈中。不会再新创建栈、task。

singleTop模式

如果把A设为默认Standard标准模式,把B设置singleTop模式,A启动B后看看什么情况,相关源码较简单,不再添加,本文后又源码下载地址。

在stack #1中,新创建了一个task #25,包含B实例和A实例,新启动的实例位于栈顶。如果在B中点击按钮再次启动B,发现栈信息不会改变,而且无论点击多少次按钮,stack #1栈中还是B和A,不会重新创建实例。

假设在A中启动B,B启动C,C设为标准模式,启动后的栈信息:

栈顶是C,其次是B和A,A在栈最底部;如果此时在C中点击按钮再启动B呢?启动后的栈信息:

发现栈顶又创建了一个B实例,不会复用栈中已有的实例,栈中总共有2个B实例!

singleTop模式跟标准Standard模式差不多,只不过多了一种情况,分为两种情况来看:

1.  如果栈中已经有了待启动activity实例并且位于栈顶,那么再次启动该activity时,系统会直接复用该实例,不会再创建新的实例;如果没有,就新创建实例,并放到栈顶;

2. 如果栈中已经有了待启动activity实例,但不在栈顶,那么再次启动该activity时,系统会再次创建新的实例并将该实例放到栈顶,这种情况和standard模式一样。

singleTask模式

如果A和C设置standard模式,B设为singleTask模式,A启动B,B启动C,按照这个顺序启动后,栈中自底向上为:A—–B—–C,如果此时在C中点击按钮再次启动B呢?启动后栈信息为:

此时,Task #30中只有A和B,B位于栈顶,没有C了,这个和singleTop有了明显的差别,在singleTop中C不会消失,而此时C却消失了。

1.  如果栈中已经有了待启动activity实例并且位于栈顶,那么再次启动该activity时,系统会直接复用该实例,不会再创建新的实例;如果没有,就新创建实例,并放到栈顶;

2. 如果栈中已经有了待启动activity实例但不在栈顶,那么再次启动该activity时,系统会复用已有实例,并且把位于该实例之上的所有其他activity实例移出栈,同时将该实例放在栈顶。

singleInstance模式

如果设A和C为standard模式,B为singleInstance模式,A启动B后栈信息为:

发现和上面三种情况都不一样的地方,在栈中新创建了一个task,并把B放入其中,上面三种情况都是在同样的task中。如果再B中启动C,启动后的栈:

A和C都是标准模式,都在同一个task中,而B在另外一个task中,因为启动了C,C在栈顶。如果再C中点击按钮再次启动B,结果会是什么?

B所在的task跑到了栈顶,A和C所在的task在栈底。而且B始终只有一个实例。

1.  如果栈中没有待启动activity实例,启动该activity时,系统会新创建一个task,再创建一个待启动activity实例,把该实例放到新task中,并且该task会在栈顶;

2. 如果栈中已经有了待启动activity实例,不管在栈的什么位置,系统都会复用已存在实例,并且把该实例放在栈顶,而且该task中只有一个该实例,不会再有第二个实例,也不会有其他activity实例;

3. 如果一个应用中有多个activity都设置成singleInstance模式,那么每个启动后的activity实例都保存在一个task中,不会在同一个task中,task和实例是一对一关系。

同一应用中测试小结

a. standard、singleTop存在多种实例的可能(“可能”二字表明,singleTop情况下,如果栈顶已有实例,再次启动时只会复用,如果不在栈顶,就会新创建实例);而singleTask和singleInstance只有一个实例,再次启动时不会创建新实例;

b. singleTask和singleInstance模式,再次调用时都会先调用onNewIntent方法,再调用onResume方法;对于singleTop,如果栈顶已有实例,也是先调用onNewIntent方法,再调用onResume方法,如果不在栈顶或者还没有实例,就会先调用onCreate方法;

c. singleInstance模式不同于其他三种,首次启动时会新开启一个task,该task只包含一个实例;再次启动时只会复用该task,不再新创建。

同一应用中只有1个app,源码地址:https://yunpan.cn/crybfHCWhcbwW  访问密码:e7cb

不同应用之间测试小结

上面分析了在同一应用中的情况,再看看不同应用之间的情形。通过测试得知:standard、singleTop没有什么改变,还是在在同样的栈、task中;singleInstance模式下也没有改变,还是会创建新的task并保存唯一实例;但singleTask却不一样,首次启动时,系统会在当前栈中创建一个新的task,再次启动时,复用已有task;而在同一应用中,再次启动时,不会再创建新task的,直接复用已有task。

不同应用之间测试有2个app,源码地址:https://yunpan.cn/crKLt2CuZ7drc  访问密码 e4b8

最终总结

不管是同一应用中还是不同应用之间,standard、singleTop、singleInstance各自没有区别,只有singleTask不一样,同一应用中不创建新的task,不同应用中有可能会创建新的task。(注:这里用到了“可能”二字,没有用“一定”,是因为这与taskAffinity属性有关,如果设置了此属性,就会在该属性对应的task中启动实例,否则,会创建新的task)。

转自:feeyan

Android启动activity的4种模式(standard、singleTop、singleTask、singleINstance)的更多相关文章

  1. Android -- Activity的生命周期,Activity四种启动模式 Standard, SingleTop,SingleTask,SingleInstance

    1. 示例图 . 这七个方法定义了Activity的完整生命周期.实现这些方法可以帮助我们监视其中的三个嵌套生命周期循环:  Activity的完整生命周期自第一次调用onCreate()开始,直至调 ...

  2. Android启动Activity的两种方式与四种启动模式

    1.在一个Activity中调用startActivity()方法 2.在一个Activity中调用startActivityRequest()方法. 重写onActivityResult方法,用来接 ...

  3. Android学习笔记_50_(转 四种加载方式详解(standard singleTop singleTask singleInstance)

    Android之四种加载方式 (http://marshal.easymorse.com/archives/2950 图片) 在多Activity开发中,有可能是自己应用之间的Activity跳转,或 ...

  4. Android 四种加载方式详解(standard singleTop singleTask singleInstance) .

    Android之四种加载方式 (http://marshal.easymorse.com/archives/2950 图片) 在多Activity开发中,有可能是自己应用之间的Activity跳转,或 ...

  5. Activity的启动模式全解standard,singleTop,singleTask,singleInstance

    在android中控制Activity的启动模式的属性主要控制两大功能: 1,控制activity 进入哪一个任务task 中,   有两种可能,进入启动task中,进入指定taskAffinity的 ...

  6. "standard,singleTop,singleTask,singleInstance"-Android启动模式

    安卓有4种启动模式,下面我们就进行详细的讲解 用栈的思维去理解,就能理解这些启动模式的本质了 先设置两个页面: A(为测试对象),B两个页面,两个页面都有跳至对方的按钮 一.标准模式(standard ...

  7. Android [启动方式:standard singleTop singleTask singleInstance]

    栈顶Activity是当前正在显示的. 以A.B举例 1.standard 不同的Activity都存放在同一个栈中,每次创建实例都会堆放到栈顶,逐次返回直至退出. 创建实例B 创建实例A 点击返回时 ...

  8. Android 启动Activity的方式

    Activity的启动分为两种方式,显示方式和隐式方式,显示方式就是在通过intent启动Activity时指定了Activity的包名和类名. 而隐式方式则在初始化Intent时仅仅指定action ...

  9. Android系统中的6种模式

    Android系统中的6种模式 1:一般启动模式(normal mode):    功能是正常启动手机,方法为关机状态下按电源键启动. 2:安全模式(safe mode):    此模式和正常启动一样 ...

随机推荐

  1. 去除List集合中的重复对象,Map遍历代码

    /*** * 去除List<PartsInfoDTO>列表中的重复对象 ~!! * @param list * @return */ public static List<Parts ...

  2. Window 8.1 开启Wifi共享

    p{padding-left:20px;} Hosted network supported:Yes  支持Wifi共享 命令:netsh wlan set hostednetwork mode=al ...

  3. oracle RAC--归档日志的开启方法

    oracle RAC--归档日志的开启方法 2011-10-07 15:53:04 分类: Oracle oracle RAC--归档日志的开启方法   ======================= ...

  4. POJ 1852

    #include <iostream> using namespace std; int main() { //freopen("acm.acm","r&qu ...

  5. hdu 4427 Math Magic DP

    思路: dp[i][j][k]表示满足前i个数,和为j,lcm为k的数目. 设a为解的第i+1个数. 那么状态转移就为 dp[i+1][j+a][lcm(a,k)]+=dp[i][j][k]. 但是由 ...

  6. Xamarin.Android 入门之:Bind java的jar文件+Android显示gif图片

    一.引言 在xamarin开发的时候,有时我们想要做一个功能,但是这个功能已经有人用java写好了,并且打包成了jar文件.那么我们可以直接把对方的jar文件拿过来用而不是重新用c#写代码. 关于bi ...

  7. Android 自定义Android带图片和文字的ImageButton

    经过分析,上述按钮效果实际上就是一个布局,一个最简单不过的垂直线性布局,上部分是一个ImageView,下部分是一个TextView,这个布局可点击.可设置监听. 我们首先要编写自己的ImageBut ...

  8. android为应用程序添加退出动画

    原本想搞一个退出程序时,把前一个应用程序的VIEW或者截图抓过来为我用,以实现更复杂的动画效果,尝试了很多方法,但都有或多或少的缺陷,可惜最后失败了.不过也算有所得.写文以标记. 其实抓图在4.0以后 ...

  9. web前端性能测试小点

    关于前端性能的文章: http://www.cnblogs.com/fnng/archive/2011/09/19/2181894.html web应用的前端性能响应时间指浏览器的页面加载时间.浏览器 ...

  10. IOS数据类型

    id – 动态对象类型.动态类型和静态类型对象的否定词汇为 nil. Class – 动态类的类型.它的否定词汇为 Nil.SEL – 选择器的数据类型(typedef):这种数据类型代表运行时的一种 ...