Activity的四种启动方式

Activity的四种启动模式

Android开发者在AndroidManifest文件中一共设计了四种启动模式

  • standard
  • singleTop
  • singleTask
  • singleInstance

一、Android 任务栈

在了解Acvitity的四种启动模式之前,我们必须了解Android任务栈的概念

栈:先进后出的线性表
一个android应用程序功能通常会被拆分为多个Activity,而各个Activity之间通过Intent进行连接,android系统通过栈结构来保存整个程序的Activity,栈底的原始是整个栈任务的发起者。
正常情况下,当一个Activity启动了另一个Activity的时候,新启动的Activity就会置于任务栈的顶端,二启动它的Activity虽然功成身退,但依然保留在任务栈中,处于停止状态(如果没有finish),当用户按下返回键或者调用finish()方法时,系统会移除顶部的Activity,让后面的Activity恢复活动状态。但是,可以给Activity设置一些“特权”,来打破这种“和谐”的模式。这种特权,就是通过在AndroidManifest.xml文件中的属性android:launchMode来设置或者通过Intent的flag来设置的。

      <activity android:name=".MainActivity"
            android:launchMode="standard">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        Intent intent = new Intent(this,MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
     // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

二、四种启动模式

  • standard
  • singleTop
  • singleTask
  • singleInstance

2.1 standard

默认启动模式,当不指定Activity的启动模式,则使用这种启动方式启动Activity;这种启动方式每次都会创建新的实例,新的activity会覆盖在原来的activity上。

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.e(TAG, "onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testLauncherMode();
            }
        });
    }

    void testLauncherMode() {
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
    }

这里写图片描述
模型如下
这里写图片描述

2.2 singleTop

如果指定启动模式为singleTop模式,那么在启动时,系统会判断当前栈顶的Activity是不是要启动的Activity,如果是则不创建新的Activity而直接引用这个Activity;如果不是,则创建新的Activity.

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate");
        setContentView(R.layout.view_second);

        Button button = (Button) findViewById(R.id.button2);
        Button btnMySelf = findViewById(R.id.button3);
        btnMySelf.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startMySelf();
            }
        });
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testSingleTopLauncherMode();
            }
        });
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.e(TAG,"onNewIntent");
    }

这里写图片描述
模型如下
这里写图片描述

2.3 singleTask

参考自
作者:JxYoung
链接:https://www.jianshu.com/p/4c8d6e2117ac
来源:简书

这种启动模式的Activity在Android系统中只允许存在一个实例

如果系统中已经存在了该种启动模式的目标Activity,则系统并不会重新创建一个目标Activity,而是首先将持有目标Activity的整个任务栈都会被置于前台(用户可见),并且通过onNewIntent(
)方法将启动目标Activity的Intent传递给目标Activity,置于目标Activity拿到这个Intent之后要做什么操作,系统就不管了,随便你拿来干什么。

但是这里有个问题,就是目标Activity和源Activity是不是来自同一应用。

源Activity和目标Activity来自同一个应用

这种情况还要分两种情况说:

当前系统中还没有目标Activity的实例
这种情况最简单,直接在当前的任务栈中创建SingleTask模式的Activity并置于栈顶即可。

当前系统中已经存在目标Activity的实例
这种情况比较特殊,因为系统会把任务栈中目标Activity之上的所有Activity销毁,以让目标Activity处在栈顶的位置。

这里还要还要再提醒大家的是,因为目标Activity已经存在,系统不会重新创建,而是通过onNewIntent()的方式把Intent传递过来,这点和singleTop模式有些类似
这里写图片描述

这里写图片描述

源Activity和目标Activity来自不同应用 这种情况也要分两种情况说:

当前系统中还没有目标Activity的实例
这时系统首先会看任务管理器中是否有目标Actvity所在应用的任务栈?如果有的话,那就直接在目标Activity所在应用的任务栈的栈顶创建即可。

如果任务管理器中没有目标Activity所在应用的任务栈,系统就会创建其所在应用的任务栈和目标Activity,并且把目标Activity作为新建任务栈的根Activity。如下图所示
这里写图片描述

当前系统中已经存在目标Activity的实例
目标Activity所在任务栈会被置于前台(即用户可见),而且也会把目标Activity之上的所有Actvity全部销毁。

2.4 singleInstance

这种启动模式和singleTask几乎一样,它也只允许系统中存在一个目标Activity,包括上面我们所说的SingleTask的一些特性singleInstance都有。singleInstance翻译过来是单例的意思:TA有两层含义:1.告诉系统,我是独一无二的,2.告诉任务栈我是独一无二的,也就是说,任务栈中除了我不能再有其他Activity。

所以,如果要启动singleInstance模式的Activity,那只能新创建一个任务栈用来放它,因为人家说了,“我是独一无二的!”。同样的,如果从这种启动模式的Activity中启动别的Activity,那不好意思,我不管你是不是和我处在同一个应用,我所在的任务栈只能拥有我一个人,您呐,另外让系统给你创建一个任务栈待着去吧。

三、启动模式的使用

3.1 在AndroidManifest.xml文件中配置

      <activity android:name=".MainActivity"
            android:launchMode="standard">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

3.2 通过Intent添加标志来识别

        Intent intent = new Intent(this,MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
     // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

常用的Flag

  • INTENT.FLAG_ACTIVITY_NEW_TASK

    使用一个新的Task来启动一个Activity,但启动的每个Activity都将在一个系的Task中。该Flag通常用来从Service中启动Activity的场景,由于在Service中并不存在Activity栈,所以使用该Flag来创建一个新的Activity栈,并创建新的Activity实例。

  • INTENT.FLAG_ACTIVITY_SINGLE_TOP

    等同于android:launchMode=”singleTop”

  • INTENT.FLAG_ACTIVITY_CLEAR_TOP

    等同于android:launchMode=”singleTask”

  • INTENT.FLAG_ACTIVITY_NO_HISTORY

    使用这种模式启动Activity,当该Activity启动其他Activity后,该Activity就消失了,不会保留在Activity栈中,例如A-B,B以这种模式启动C,C在启动D,则当前Activity栈为ABD。

文章写到这,希望对给位有所帮助,谢谢观看。

参考文献:
https://www.jianshu.com/p/4c8d6e2117ac
http://blog.csdn.net/x283930450/article/details/70597555

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章