Activity有四种启动模式:,singleTop,singleTask,singleInstance.

可以在AndroidManifest.xml中通过给<activity>标签指定android:launchMode属性来选择启动模式。

standard:默认启动模式

standard是Activity默认的启动模式,在不进行显示指定的情况下,所有Activity都会自动使用这种启动模式。

Android是用返回栈来管理Activity的,在standard模式下,每当启动一个新的Activity,它就会入返回栈中,并处于栈顶的位置。

对于这种模式的Activity,系统不会在乎该Activity是否已经在返回栈中存在,每次启动都会创建一个该Activity的实例。

package com.java.androidstudy;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class FirstActivity extends AppCompatActivity {
    private static final String TGA = "FirstActivity";
    private  Button btn_first;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);
        Log.d(TGA,"onCreate()"+this.toString());
        initView();
        initListener();
    }

    private void initListener() {
        btn_first.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this,FirstActivity.class);
                startActivity(intent);
            }
        });
    }

    private void initView() {
        btn_first = findViewById(R.id.btn_first);
    }

    @Override
    protected void onDestroy() { 
        super.onDestroy();
        Log.d(TGA,"onDestroy()"+this.toString());
    }
}

 

上述代码为:在FirstActivity的基础上启动FirstActivity.这没啥意义,只是为了演示standard模式。这里我们点击四下按钮,并将该Activity打印出来。

android 活动 android活动组件启动模式_启动模式

 

 

 日志信息:

android 活动 android活动组件启动模式_android 活动_02

 

 

 可以看到每一次点击都创建了新的实例在返回栈中。栈是先进后出的数据结构。如下图:

android 活动 android活动组件启动模式_ide_03

 

 

 现在返回栈中有这么四个实例,现在我按下返回键,@a641637会首先出栈,然后是@8d8a58b,@9d24af9,最后是@5a89e59,这样才退出了程序。

看看日志:

android 活动 android活动组件启动模式_android 活动_04

 

 上面为创建Activity时的顺序,红框内的为销毁Activity时的顺序。

很直白的看到了该模式的特点:每一次启动Activity都会创建新的实例,入栈。创建多少个Activity就要点击多少下返回键才能退出。

SingleTop:

你可能觉得standard模式不太合理,Activity明明已经在栈顶了,再次启动时却还能创建一个新的实例。

现在我们来看看SingleTop模式。

它会判断栈顶是否为该Activity,如果是,则直接使用。不是,则创建新的该Activity。

使用场景:一般来说,为了保证只有一个任务,而不被创建多个,所以需要这种模式。如:浏览器的书签,应用的通知推送。

 

修改为SingleTop模式:‘

<activity
            android:name=".FirstActivity"
            android:launchMode="singleTop">  //启动模式
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

这样之后,我们再次多次点击FirstActivity中的启动按钮。只会创建一个Activity的实例。

因为该FirstActivity已经位于栈顶,再次点击使其启动FirstActivity,则可以直接使用。

日志信息如下:

android 活动 android活动组件启动模式_android 活动_05

 

 只需按一次返回键就可以退出程序。

 

现在我们对FirstActivity进行修改。

FirstActivity:
package com.java.androidstudy;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class FirstActivity extends AppCompatActivity {
    private static final String TGA = "FirstActivity";
    private  Button btn_first;
    private Button btn_second;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);
        Log.d(TGA,"onCreate()"+this.toString());
        initView();
        initListener();
    }

    private void initListener() {
        btn_first.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this,FirstActivity.class);
                startActivity(intent);
            }
        });

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

    private void initView() {
        btn_first = findViewById(R.id.btn_first);
        btn_second = findViewById(R.id.btn_second);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TGA,"onDestroy()"+this.toString());
    }
}
界面效果:

 

SecondActivity:

package com.java.androidstudy;



import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;

public class SecondActivity extends AppCompatActivity {
    private static final String TGA = "SecondActivity";
    private Button btn_first;
    private Button btn_second;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Log.d(TGA,"onCreate()"+this.toString());
        initView();
        initListener();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TGA,"onDestroy()"+this.toString());
    }


    private void initListener() {
        btn_first.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(SecondActivity.this,FirstActivity.class);
                startActivity(intent);
            }
        });

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

    private void initView() {
        btn_first = findViewById(R.id.btn_first);
        btn_second = findViewById(R.id.btn_second);
    }

}
界面效果:

现在FirstActivity的启动模式是SingleTop,而SecondActivity的启动模式是standard.

运行程序后:

首先创建了FirstActivity的实例,日志如下:

android 活动 android活动组件启动模式_android_06

 

 

 然后点击跳转到第二个界面,日志如下:

android 活动 android活动组件启动模式_android_07

 

 可以看到,创建了SecondActivity的实例,此刻栈顶是SecondActivity@1a0ef8f。现在返回栈中位置如下图:

android 活动 android活动组件启动模式_启动模式_08

 

 我们点击跳转到第一个页面:

android 活动 android活动组件启动模式_android_09

 

 因为栈顶是SecondActivity@1a0ef8f,所以新增了一个FirstActivity的实例。

此刻返回栈如下:

android 活动 android活动组件启动模式_android 活动_10

  现在我们退出程序需要按三下返回键。

完整日志如下:

android 活动 android活动组件启动模式_启动模式_11

SingleTask:

每次启动Activity时,该模式会检查栈中是否存在该Activity的实例,
如果存在会让该Activity之上的所有其她Activity统统出栈,
如果没有就会创建一个新的Activity实例。

 首先修改AndroidManifest.xml中的FirstActivity的启动模式

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

 此刻FirstActivity的启动模式为SingleTask,SecondActivity的启动模式为standard。

在启动FirstActivity时,应在返回栈中检查是否已经存在该Activity,若存在,则让该Activity之上的所有Activity出栈。这种情况下,FirstActivity是从不可见没有焦点的停止状态重新位于栈顶,应会执行onRestart()方法。在FirstActivity中重写onRestart()方法,并打印信息。

android 活动 android活动组件启动模式_android 活动_12

 

 现在我先点击三下第一个按钮,再点击第二个按钮。

日志信息如下:

android 活动 android活动组件启动模式_android 活动_13

 可以看到此刻返回栈中应如下:

android 活动 android活动组件启动模式_ide_14

 此刻我再次点击第一个按钮,日志信息打印如下:

android 活动 android活动组件启动模式_启动模式_15

 可以看到SecondActivity全部出栈,FirstActivity中执行了onRestart()方法重新成为栈顶。出栈顺序为先销毁上面最近的Activity,待上面的Activity是栈顶后,先onRestart(),再销毁栈顶。

SingleInstance:

指定为singleInstance模式的Activity会启动一个新的返回栈来管理这个Activity,

singleInstance。

启动模拟器:

android 活动 android活动组件启动模式_android 活动_16

 

 

 点击一下第一个按钮,再点击一下第二个按钮,再点击一下第一个按钮。

日志如下:

android 活动 android活动组件启动模式_启动模式_17

此刻537的返回栈在538的上面,销毁时,537全部销毁完,才轮到538。如下图:

android 活动 android活动组件启动模式_启动模式_18