前言
- AndroidStudio 版本: Android Studio Iguana | 2023.2.1
- 项目语言: Java
- JDK版本: 17
- 对应的android版本:12
前置文章
Activity组件的生命周期 - 掘金 (juejin.cn)
什么是Activity的启动模式
在 Activity组件的生命周期 - 掘金 (juejin.cn)这篇文章中已经讲到 Activity 的调用其实也是通过 返回栈来实现的,返回栈就是用来存储活动(Activity)的,那么启动模式和返回栈有什么关系呢?这是因为所谓的启动模式就是当启动一个新的 Activity 的时候需要根据返回栈中是否已经存在对应类型的 Activity 而做出不同的行为。
Activity启动模式的配置
Activity 的启动模式配置是在 AndroidManifest.xml 文件中是 <activity> 标签中通过 android:launchMode="standard" 属性来配置的,如下所示
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ADemo"
tools:targetApi="31">
<activity
android:name=".SecondActivity"
android:exported="true"
android:launchMode="standard">
<intent-filter>
<action android:name="com.example.ademo.MainActivity.MAIN_ACTION" />
<action android:name="com.example.ademo.MainActivity.MAIN_ACTION2" />
<!-- 这里需要注意的是,即使有其他的 category,默认的category还是需要加上 -->
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.example.ademo.MainActivity.CATEGORY_ONE" />
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
如果没有配置的话,默认就是 standard 类型
Activity启动模式的类型
Activity 的启动模式一共有四种类型
- standard,这个也是默认值
standard
- 当启动一个新的 Activity 的时候,不论返回栈中是否存在同类型的 Activity,新的 Activity 都是会加入返回栈的
代码示例
现在在 MainActivity 中再次启动 MainActivity,MainActivity 中的代码示例如下
package com.example.ademo;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import androidx.activity.EdgeToEdge;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// 通过这个日志查看每次创建的 Activity 实例id,如果多次创建是同一个id说明实例相同
Log.d("MainActivity", "开始创建主Activity" + this);
super.onCreate(savedInstanceState);
//EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
// 通过 findViewById 方法获取 Button 实例
Button button = (Button)findViewById(R.id.cus_button);
// 给 button 设置点击监听器
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 在MainActivity 中再次启动 MainActivity 活动,这样返回栈中就有两个 MainActivity
startActivity(new Intent(MainActivity.this, MainActivity.class));
}
});
}
}
在 LogCat 中查看日志如下
2024-04-14 12:09:22.935 16622-16622 MainActivity com.example.ademo D 开始创建主Activitycom.example.ademo.MainActivity@a059f8c
2024-04-14 12:09:36.904 16622-16622 MainActivity com.example.ademo D 开始创建主Activitycom.example.ademo.MainActivity@4bc86d1
可以看到两次的对象是不同的,这就是 standard 模式,即只要是新启动 Activity,不论返回栈中是否存在,都会创建一个新的 Activity 对象放入返回栈中
singleTop
- 当活动的启动模式指定为 singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例
- 对于 MainActivity 还是使用上面的代码不变,只需要将 AndroidManifest.xml 中的 MainActivity 的启动模式修改成 singleTop 然后再次验证即可,此时会发现不论点击多少次 Button, MainActivity 中的 onCreate 方法只会被调用一次,这是因为当前栈顶的 Activity 就是 MainActivity, 当我们点击 MainActivity 中的 Button 去创建 MainActivity 的时候是直接使用栈顶的 MainActivity 而不是新创建一个 Activity 放入返回栈
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
singleTask
- singleTop 模式是只有即将要创建的 Activity 在栈顶的时候才会复用栈顶的 Activity,如果即将要启动的 Activity 不是在栈顶的时候还是会创建新的 Activity
- 使用 singleTask 则可以做到即使即将要创建的 Activity 不是在栈顶,但是在返回栈中也是存在的,那么就会将对应 Activity 前面的那些 Activity 都弹出栈,这样一来这个 Activity 就是会在栈顶了,只有在返回栈中没有发现对应的 Activity 才会去创建对应的 Activity
singleInstance
- singleInstance 模式实际是新创建一个返回栈来管理对应的 Activity
- 正常模式下新创建一个 Activity 是直接将对应的 Activity 添加到原本的返回栈中即可,但是对于使用 singleInstance 启动模式的 Activity 则是将这个 Activity 放入在一个新的返回栈中