Activity启动模式

一、启动模式简介

  启动模式相当于Activity的一个属性,不同的启动模式Activity会有不同的行为表现,这里的行为主要体现在Activity的生命周期,特别是系统在启动多个Activity实例的时候,具体差异我们将用实例来说明。

二、任务栈简介

  要了解Activity的启动模式,就不可避免地涉及到Activity所需的任务栈。什么是任务栈呢?android系统每启动一个新的Activity,都要将该Activity实例放入特定的任务栈,而这个任务栈和一个参数TaskAffinity有关,这个产生标识了Activity所需的任务栈的名字,默认的值为应用的包名。值得注意的是,TaskAffinity属性主要和singleTask启动模式(下面将要介绍)或allowTaskReparenting属性配合使用,在其他情况下没有意义。
  既然叫“栈”,那么就符合“后进先出”的特点,我们每按一下back键,就有一个Activity实例出栈。

三、Activity启动模式

1、standard

  标准模式,这是系统的默认模式。每次启动一个Activity都会重新创建一个Activity实例,不管这个Activity的实例是否存在。

2、singleTop

  栈顶复用模式。在这种模式下,如果有Activity实例位于任务栈顶,那么就不会重新创建Activity实例,同时,Activity的onNewIntent方法会被回调。

3、singleTask

  栈内复用模式。类似于单例模式,只要任务栈中有一个此Activity的实例,那么重新启动Activity就不会创建新的实例,而且和singleTop一样,onNewIntent方法会被回调

4、singleInstance

  单实例模式,这是一种加强的singleTask模式,只要有一个任务栈中有Activity的实例,那么新实例就不会被创建。换句话说,singleInstance的Activity实例只能位于一个任务栈中。

下面我将用运行实例代码结合日志输出来分析各种启动模式的区别

代码:
LaunchMode应用:

package com.android.yanghuaan.launchmode;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class AActivity extends AppCompatActivity {

    private static final String TAG = "Activity_A";

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

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "created.");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        findViewById(R.id.start_B_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), BActivity.class);
                startActivity(intent);

            }
        });
        findViewById(R.id.start_A_self_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), AActivity.class);
                startActivity(intent);
            }
        });
    }

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

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

    @Override
    protected void onDestroy() {
        Log.d(TAG, "destroyed.");
        super.onDestroy();
    }
}
package com.android.yanghuaan.launchmode;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class BActivity extends AppCompatActivity {

    private static final String TAG = "Activity_B";

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

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "created.");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);
        findViewById(R.id.start_A_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), AActivity.class);
                startActivity(intent);

            }
        });
        findViewById(R.id.start_B_self_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), BActivity.class);
                startActivity(intent);
            }
        });
    }

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

    @Override
    protected void onDestroy() {
        Log.d(TAG, "destroyed.");
        super.onDestroy();
    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.android.yanghuaan.launchmode">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!--主要在activity中改变启动模式,不同启动模式下此处代码不同-->
        <activity
            android:name=".AActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".BActivity">
        </activity>
    </application>
</manifest>

  LaunchMode应用包含两个Activity–A和B,每个Activity都有两个按钮,一个用来启动自己,另一个用来启动另一个Activity。
LaunchMode2代码:

package com.android.yanghuaan.launchmode2;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.start_other_activity_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setClassName("com.android.yanghuaan.launchmode",
                        "com.android.yanghuaan.launchmode.AActivity");
                startActivity(intent);
            }
        });
    }
}

  LaunchMode2应用包含一个Activity,它可以用来启动LaunchMode应用的一个Activity。只有在singleInstance的例子中才使用到LaunchMode2应用,因此写好只需跑一次、将LaunchMode2安装到安卓手机上即可。

  通过在Activity的生命周期方法中添加输出日志的代码来追踪每个Activity的活动

standard 模式

<activity
            android:name=".AActivity"
            android:launchMode="standard">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".BActivity">
        </activity>

操作步骤:
  进入LaunchMode应用后点击两次启动自己的按钮
日志输出:

06-13 20:25:07.982 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:25:08.201 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:25:08.201 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:25:11.399 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:25:11.422 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:25:11.423 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:25:14.589 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:25:14.614 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:25:14.614 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: resumed.

分析:
  从日志可以看出,onCreate->onStart->onResume被被调用了3次,说明创建了3个AActivity的实例,即Activity实例被重复创建了。此时需要3次按back才能返回桌面

singleTop 模式

<activity
            android:name=".AActivity"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".BActivity"
            android:launchMode="singleTop">
        </activity>

操作步骤:
  进入LaunchMode应用后先按启动BActivity的按钮,此时进入了BActivity;再按启动AActivity的按钮,此时进入了AActivity;再按两次启动自己(AActivity)的按钮
日志输出:

06-13 20:35:07.446 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:35:07.483 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:35:07.483 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:35:10.828 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: created.
06-13 20:35:10.860 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: started.
06-13 20:35:10.860 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: resumed.
06-13 20:35:12.033 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:35:12.068 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:35:12.068 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:35:16.913 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: new intent
06-13 20:35:16.913 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:35:19.872 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: new intent
06-13 20:35:19.873 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:35:24.084 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: restarted.
06-13 20:35:24.084 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: started.
06-13 20:35:24.084 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: resumed.
06-13 20:35:24.394 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: destroyed.
06-13 20:35:24.951 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: restarted.
06-13 20:35:24.951 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:35:24.951 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:35:25.252 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: destroyed.
06-13 20:35:27.292 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: destroyed.

分析:
  从AActivity到BActivity,再启动AActivity,发现onCreate被调用,即表明AActivity实例被重新创建;根据栈的特点可知此时AActivity的实例并没有位于栈顶,所以AActivity实例被重新创建;
  返回AActivity后,再次启动两次AActivity都发现只有onResume和onNewIntent被调用,可知AActivity的实例被重新使用,并没有创建新的实例,这两次创建Activity的过程中AActivity的实例都位于栈顶,所以没有重新创建。
  此时连续按back键的效果是:BActivity->AActivity->桌面;

singleTask 模式

<activity
            android:name=".AActivity"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".BActivity">
        </activity>

操作步骤:
  进入LaunchMode应用,按启动BActivity的按钮启动BActivity,再按启动AActivity的按钮启动AActivity
日志输出:

06-13 21:21:09.731 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 21:21:09.760 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 21:21:09.760 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 21:21:12.204 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: restarted.
06-13 21:21:12.204 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: started.
06-13 21:21:12.204 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: resumed.
06-13 21:21:13.889 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: new intent
06-13 21:21:13.889 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: restarted.
06-13 21:21:13.890 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 21:21:13.890 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.

分析:
  从BActivity启动AActivity,发现onRestart被调用,同时onNewIntent也被调用,表明AActivity的实例并没有被重新创建;此时只需按一次back键就可以返回桌面,因为在从BActivity创建AActivity的过程中BActivity被出栈了。

singleInstance 模式

<activity
            android:name=".AActivity"
            android:launchMode="singleInstance"
            android:allowTaskReparenting="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".BActivity">
        </activity>

操作步骤:
  先启动应用LuanchMode,再按启动BActivity的按钮启动BActivity;然后通过 home键返回桌面,启动LaunchMode2应用,在里面按启动其他应用Activity的按钮启动AActivity;最后通过 home键返回桌面,启动LaunchMode应用
日志输出:

06-13 20:55:40.044 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:55:40.136 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:55:40.137 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:55:41.046 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: created.
06-13 20:55:41.079 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: started.
06-13 20:55:41.079 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: resumed.
06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: new intent
06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: restarted.
06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:56:00.336 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: new intent
06-13 20:56:00.336 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: restarted.
06-13 20:56:00.337 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:56:00.337 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.

分析:
  从LaunchMode2启动AActivity,发现AActivity并没有被重新创建,而是调用了onNewIntent和onRestart,并且重新从桌面进入LaunchMode应用也是如此,看起来就像AActivity从一个任务栈中移动到另一个任务栈中,这充分说明了singleInstance模式的Activity只能存在于一个任务栈中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值