Activity的四种启动模式解析

任务栈

我们都知道,每启动一个Activity时,系统会将其压入到一个任务栈中,当我们使用back键时,被返回的Activity会从任务栈中弹出,直到栈空为止。当任务栈中没有Activity时,系统会回收掉这个任务栈。
然而什么是任务栈呢?
默认情况下,所有Activity所需的任务栈的名字为应用的包名
参数:TaskAffinity(任务相关性) :标识了一个Activity所需要的任务栈的名字。 此属性主要和singleTask配对使用。

任务栈有两种:

* 前台任务栈
* 后台任务栈 处于暂停状态
四种启动模式:
standard 标准模式(默认的模式)

每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否存在。一个任务栈可以有多个实例,每个实例可以属于不同的任务栈。

例子
现在已启动MainActivity(用Main表示),那么系统会将该Activity压入栈中。如果在MainActivity中要启动MainActivity,结果会怎样呢?我们看如下代码

<!-- launchMode属性设置Activity为标准模式 -->
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="standard" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

我们在MainActivity中启动MainActivity。代码如下

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    Button btn_launch;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate()");

        btn_launch = (Button) findViewById(R.id.btn_launch);
        btn_launch.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, MainActivity.class);
                startActivity(intent);
            }
        });
    }
}

运行结果为:
这里写图片描述

我们看到,MainActivity执行了两次onCreate()方法 。表明不管MainActivity是否在任务栈栈顶,启动MainActivity都会重新创建一次。

singleTop 栈顶复用模式

如果新Activity位于任务栈的栈顶,那么此Activity不会被重新创建,系统会调用其onNewIntent()。如果新Activity没有位于任务栈的栈顶,那么此Activity会被重新创建并位于任务栈栈顶。
例子:
如果任务栈中有MainActivity和SecondActivity,SecondActivity位于栈顶,且SecondActivity的启动模式为singleTop。那么,现在需要启动SecondActivity,系统是否会重新创建SecondActivity呢?答案是:SecondActivity不会重新创建。
代码如下

<!-- launchMode属性设置Activity为标准模式 -->
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="standard" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <!-- launchMode属性设置Activity为singleTop启动模式 -->
        <activity
            android:name=".SecondActivity"
            android:label="@string/title_activity_second"
            android:launchMode="singleTop"
             >
        </activity>

MainActivity的代码

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    Button btn_launch_second;

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

        btn_launch_second = (Button) findViewById(R.id.btn_launch_second);
        btn_launch_second.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }

SecondActivity代码

public class SecondActivity extends Activity {
    private static final String TAG = "SecondActivity";
    Button btn_launch_third;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Log.d(TAG, "onCreate()");
        btn_launch_third = (Button) findViewById(R.id.btn_launch_third);

        btn_launch_third.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(SecondActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }

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

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause()");
    }

}

输出结果为:
这里写图片描述
当再次启动SecondActivity时,系统不会重新创建Activity实例,而是调用它的onNewIntent()方法。

现在,我们考虑另外一种情况。如果MainActivity为singleTop启动模式,而SecondActivity为标准模式,且位于任务栈栈顶。当我们需要在SecondActivity中启动MainActivity时,会出现什么情况?答案是:系统会重新创建MainActivity。
只需将上面的代码中MainActivity中的启动模式改为singleTop,并在SecondActivity中启动MainActivity即可。这里就不贴代码了。
我们看以下运行结果:
这里写图片描述
MainActivity重新创建了。

singleTask 栈内复用模式

这是一种单例模式,只要Activity在一个栈中存在,那么多次启动此Activity都不会重新创建。当一个具有singleTask模式的Activity请求启动后,比如SecondActivity。系统会首先检查是否存在SecondActivity所需要的任务栈,如果不存在,系统会先创建任务栈,再创建该Activity实例,并将其压入到该任务栈中。如果存在,系统会检查SecondActivity是否在任务栈中,如果不在任务栈中,则创建SecondActivity,如果在任务栈中,则不创建,并且将SecondActivity调到栈顶,调用它的onNewIntent()方法。
例子
如果MainActivity为标准模式,SecondActivity为singleTask模式,且位于任务栈com.nxiangbo.task01的栈底,而ThirdActivity为singleTask模式,且位于任务栈com.nxiangbo.task01的栈顶。如果要在ThirdActivity中启动SecondActivity,那么,SecondActivity是否需要重新创建?很明显,答案是:不需要重新创建SecondActivity。因为SecondActivity已经处于任务栈中,系统会弹出ThirdActivity,让SecondActivity处于栈顶。
代码如下

 <!-- launchMode属性设置Activity为标准模式 -->
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTop" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- taskAffinity属性可以标识任务栈的名字 -->
        <!-- launchMode属性设置Activity的启动模式 -->
        <activity
            android:name=".SecondActivity"
            android:label="@string/title_activity_second"
            android:taskAffinity="com.nxiangbo.task01"
            android:launchMode="singleTask"
             >
        </activity>
        <activity
            android:name=".ThirdActivity"
            android:taskAffinity="com.nxiangbo.task01"
            android:launchMode="singleTask"
            android:label="@string/title_activity_third" >
        </activity>

MainActivity代码

public class MainActivity extends Activity {
    private static final String TAG = "MainActivity";
    Button btn_launch_second;

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

        btn_launch_second = (Button) findViewById(R.id.btn_launch_second);
        btn_launch_second.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }

}

SecondActivity代码

public class SecondActivity extends Activity {
    private static final String TAG = "SecondActivity";
    Button btn_launch_third;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Log.d(TAG, "onCreate()");
        btn_launch_third = (Button) findViewById(R.id.btn_launch_third);

        btn_launch_third.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(SecondActivity.this, ThirdActivity.class);
                startActivity(intent);
            }
        });
    }

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

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause()");
    }

}

ThirdActivity代码

public class ThirdActivity extends Activity {
    private static final String TAG = "ThirdActivity";
    Button btn_launch_main;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);
        Log.d(TAG, "onCreate()");
        btn_launch_main = (Button) findViewById(R.id.btn_launch_main);
        btn_launch_main.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(ThirdActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");
    }

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

}

输出结果为:

这里写图片描述

singleInstance 单实例模式

这是一种加强的singleTask,除了具有singleTask的特性外,此种模式只能单独的位于一个栈中。

举例:

  • 如果A是singleInstance,启动A后,系统会为它创建一个新的任务栈。

我们通过阅读前面的内容,了解到可以在AndroidMenifest.xml中的Activity标签中 通过launchMode属性设置Activity的启动模式。其实,我们也可以用Intent设置标志位 来设置Activity的启动模式。

//将Activity设置为singleTask启动模式
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

两者之间的区别为

* 第二种的优先级高于第一种。
* 第一种不能为Activity设定FLAG_ACTIVITY_CLEAR_TOP标签 ;第二种无法为Activity指定singleInstance

adb shell dumpsys activity 检测Activity的任务栈

常用Activity的Flags

* FLAG_ACTIVITY_NEW_TASK ==singleTop
* FLAG_ACTIVITY_CLEAR_TOP  ==singleTask
* FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 有此标记的Activity不会出现在历史Activity列表中
源码下载地址
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值