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打印出来。
日志信息:
可以看到每一次点击都创建了新的实例在返回栈中。栈是先进后出的数据结构。如下图:
现在返回栈中有这么四个实例,现在我按下返回键,@a641637会首先出栈,然后是@8d8a58b,@9d24af9,最后是@5a89e59,这样才退出了程序。
看看日志:
上面为创建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,则可以直接使用。
日志信息如下:
只需按一次返回键就可以退出程序。
现在我们对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的实例,日志如下:
然后点击跳转到第二个界面,日志如下:
可以看到,创建了SecondActivity的实例,此刻栈顶是SecondActivity@1a0ef8f。现在返回栈中位置如下图:
我们点击跳转到第一个页面:
因为栈顶是SecondActivity@1a0ef8f,所以新增了一个FirstActivity的实例。
此刻返回栈如下:
现在我们退出程序需要按三下返回键。
完整日志如下:
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()方法,并打印信息。
现在我先点击三下第一个按钮,再点击第二个按钮。
日志信息如下:
可以看到此刻返回栈中应如下:
此刻我再次点击第一个按钮,日志信息打印如下:
可以看到SecondActivity全部出栈,FirstActivity中执行了onRestart()方法重新成为栈顶。出栈顺序为先销毁上面最近的Activity,待上面的Activity是栈顶后,先onRestart(),再销毁栈顶。
SingleInstance:
指定为singleInstance模式的Activity会启动一个新的返回栈来管理这个Activity,
singleInstance。
启动模拟器:
点击一下第一个按钮,再点击一下第二个按钮,再点击一下第一个按钮。
日志如下:
此刻537的返回栈在538的上面,销毁时,537全部销毁完,才轮到538。如下图: