4 种启动模式
Android 是以 栈
的形式管理 Activity
的,当前活动的Activity
位于栈
顶。
通过给Activity
指定启动模式
为Activity
设定了在栈
中的管理方式。
Activity
有 4 种启动模式,通过AndroidManifest.xml
中<activity>
标签的 android:launchMode
属性来设定启动模式
。
standard
当Activity
使用了 standard
模式,每启动一个该Activity
,系统都会创建一个新的该Activity
的实例并放到栈
顶,不论栈
中原先是否存在该Activity
的实例。
standard
是Activity
的默认启动模式,在没有指定启动模式的情形下,Activity
自动使用该模式。
singleTask
当Activity
使用了 singleTask
模式,每次启动该Activity
,系统都会检查栈
中原先是否存在该Activity
的实例。如果栈
中不存在该Activity
的实例,那么就创建一个新的该Activity
的实例;如果栈
中存在该Activity
的实例,那么就直接使用该实例,同时把栈
中处于该Activity
实例之上的其他Activity
实例都出栈。
singleTop
singleTop
模式与 singleTask
模式有一定区别。
当Activity
使用了 singleTop
模式,每次启动该Activity
,系统都会检查栈
顶是否是该Activity
的实例。如果栈
顶不是该Activity
的实例,那么就创建一个新的该Activity
的实例;如果栈
顶是该Activity
的实例,那么就直接使用该实例。
singleInstance
指定为 singleInstance
模式的Activity
,会启用一个新栈
(独立的栈
)来管理该Activity
。
这样做可以方便不同应用进程共享一个Activity
实例。
代码演示
让我们编写代码,运行演示,看看这几种启动模式有什么差异吧。
编写测试代码
- 在项目
ActivitySample
中创建一个类,名为BasicSingleActivity
,继承AppCompatActivity
.
Java 代码:
public class BasicSingleActivity extends AppCompatActivity {
}
Kotlin 代码:
open class BasicSingleActivity : AppCompatActivity(){
}
- 依次创建 4 个
Activity
,分别是StandardActivity
、SingleTaskActivity
、SingleTopActivity
、SingleInstanceActivity
,使它们都继承BasicSingleActivity
.
Java 代码:
public class StandardActivity extends BasicSingleActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
public class SingleTaskActivity extends BasicSingleActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
public class SingleTopActivity extends BasicSingleActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
public class SingleInstanceActivity extends BasicSingleActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Kotlin 代码:
class StandardActivity : BasicSingleActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
class SingleTaskActivity : BasicSingleActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
class SingleTopActivity : BasicSingleActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
class SingleInstanceActivity : BasicSingleActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}
- 配置
AndroidManifest.xml
清单文件,注册新创建的 4 个Activity
。
分别为它们配置一个相应的启动模式。
<activity
android:name=".SingleInstanceActivity"
android:exported="true"
android:launchMode="singleInstance" />
<activity
android:name=".SingleTopActivity"
android:exported="true"
android:launchMode="singleTop" />
<activity
android:name=".SingleTaskActivity"
android:exported="true"
android:launchMode="singleTask" />
<activity
android:name=".StandardActivity"
android:exported="true"
android:launchMode="standard" />
- 创建布局文件
activity_basic_single.xml
编辑布局内容,添加了 4 个按钮,用于启动对应的Activity
。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="30dp">
<Button
android:id="@+id/standardBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="standard"
android:textAllCaps="false" />
<Button
android:id="@+id/singleTaskBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="singleTask"
android:textAllCaps="false" />
<Button
android:id="@+id/singleTopBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="singleTop"
android:textAllCaps="false" />
<Button
android:id="@+id/singleInstanceBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="singleInstance"
android:textAllCaps="false" />
</LinearLayout>
- 加载布局文件,初始化设置
编辑BasicSingleActivity
代码,加载布局,初始化。
Java 代码:
public class BasicSingleActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_basic_single);
Log.i("launchMode_Activity", String.format("onCreate() task: %d, instance: %s", getTaskId(), this.toString()));
Button standardBtn = findViewById(R.id.standardBtn);
standardBtn.setOnClickListener(view -> {
Intent intent = new Intent(this, StandardActivity.class);
startActivity(intent);
});
Button singleTaskBtn = findViewById(R.id.singleTaskBtn);
singleTaskBtn.setOnClickListener(view -> {
Intent intent = new Intent(this, SingleTaskActivity.class);
startActivity(intent);
});
Button singleTopBtn = findViewById(R.id.singleTopBtn);
singleTopBtn.setOnClickListener(view -> {
Intent intent = new Intent(this, SingleTopActivity.class);
startActivity(intent);
});
Button singleInstanceBtn = findViewById(R.id.singleInstanceBtn);
singleInstanceBtn.setOnClickListener(view -> {
Intent intent = new Intent(this, SingleInstanceActivity.class);
startActivity(intent);
});
}
}
Kotlin 代码:
open class BasicSingleActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_basic_single)
Log.i("launchMode_Activity","onCreate() task: $taskId, instance: ${this.toString()}")
val standardBtn: Button = findViewById(R.id.standardBtn)
standardBtn.setOnClickListener{
val intent = Intent(this, StandardActivity::class.java)
startActivity(intent)
}
val singleTaskBtn: Button = findViewById(R.id.singleTaskBtn)
singleTaskBtn.setOnClickListener{
val intent = Intent(this, SingleTaskActivity::class.java)
startActivity(intent)
}
val singleTopBtn: Button = findViewById(R.id.singleTopBtn)
singleTopBtn.setOnClickListener{
val intent = Intent(this, SingleTopActivity::class.java)
startActivity(intent)
}
val singleInstanceBtn: Button = findViewById(R.id.singleInstanceBtn)
singleInstanceBtn.setOnClickListener{
val intent = Intent(this, SingleInstanceActivity::class.java)
startActivity(intent)
}
}
}
这里重写了 onCreate()
函数,加载布局,日志记录当前 Activity
所在 栈
的 id
以及当前的Activity
实例;为 4 个按钮设置事件监听,分别启动对应的 Activity
。
- 编辑项目主
Activity
的布局文件activity_my1.xml
增加一个按钮,用于启动新建的Activity
。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="30dp">
......
<Button
android:id="@+id/standardBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="standard"
android:textAllCaps="false" />
</LinearLayout>
- 编辑项目的主
Activity
,设置事件监听
编辑MyActivity1
,为新增的按钮设置点击事件,跳转至StandardActivity
Java 代码:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my1);
......
Button standardBtn = findViewById(R.id.standardBtn);
standardBtn.setOnClickListener(view -> {
Intent intent = new Intent(this, StandardActivity.class);
startActivity(intent);
});
}
Kotlin 代码:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my1)
......
val standardBtn: Button = findViewById(R.id.standardBtn)
standardBtn.setOnClickListener{
val intent = Intent(this, StandardActivity::class.java)
startActivity(intent)
}
}
项目的代码结构:
运行项目
-
运行项目,点击按钮
standard
,此时页面跳转至StandardActivity
,查看日志台:
可以看到日志输出包含了栈
的id
以及当前的Activity
实例。 -
接着点击当前页面的按钮
standard
,每跳转到新页面都这么操作,点击 3 次,查看日志台:
可以发现,每次都创建了一个新的StandardActivity
实例,并且由同一个栈
管理。 -
点击当前页面的按钮
singleTask
,
可以看到第一次点击后页面会跳转,之后再点击按钮singleTask
页面就不再跳转了。查看日志我们会发现,第一次点击按钮singleTask
会留下日志记录当前的SingleTaskActivity
实例,之后再点击按钮就不再输出这样的日志了。这个现象是由于当前Activity
指定了singleTask
启动模式,当栈
中不存在该SingleTaskActivity
的实例,那么就创建一个新的SingleTaskActivity
的实例;如果栈
中存在该SingleTaskActivity
的实例,那么就直接使用该实例,不再新建了。
-
点击当前页面的按钮
singleTop
,
可以看到第一次点击后页面会跳转,之后再点击按钮singleTop
页面就不再跳转了。查看日志我们会发现,第一次点击按钮singleTop
会留下日志记录当前的SingleTopActivity
实例,之后再点击按钮就不再输出这样的日志了。
这时再点击按钮standard
,会跳转至新页面,如果接着点击当前页面的按钮singleTop
,可以看到这一次点击后页面会跳转,之后再点击按钮singleTop
页面就不再跳转了。
这个现象是由于SingleTopActivity
指定了singleTop
启动模式,栈顶复用。
-
点击当前页面的按钮
singleInstance
,
查看日志,可见SingleInstanceActivity
所在的栈
的id
与别的Activity
不同,这是由于该Activity
设定了singleInstance
启动模式,系统为其分配了一个独立的栈
。
多实验运行演示,结合对应的知识点,加深对Activity
启动模式的理解。
项目代码地址
Java:
https://github.com/BethelDEV/shaguaAndroid/tree/main/javaSource/ActivitySampleKotlin:
https://github.com/BethelDEV/shaguaAndroid/tree/main/kotlinSource/ActivitySample