Android 四大组件——Activity
目录
一、Activity 基础概念
二、Activity 生命周期
1. 生命周期回调方法
2. 生命周期场景
触发或不触发 onPause/onStop 的 UI 组件(本质是附属的还是独立的)
三、Activity / ActionBarActivity / AppCompatActivity的区别:
四、onCreate()一个参数和两个参数的区别:
详细对比分析
1.单参数代码示例
2.双参数代码示例
五、Activity间的数据相互传递
六、关闭所有Activity和退出App
1.关闭所有Activity
2.退出App
七、屏幕旋转对Activity的影响
1.使用 onSaveInstanceState() 保存临时状态(最常用)
2.手动处理配置变更(阻止销毁重建)
3.固定 Activity 屏幕方向的方法
3.1 在 AndroidManifest.xml 中配置(推荐)
3.2 在 Java 代码中动态设置
4.使用 ViewModel + LiveData(架构组件推荐)
与其他方案的对比
八、启动模式
九、设置Activity全屏的方法
1.代码隐藏ActionBar
2.通过requestWindowFeature设置
3.通过AndroidManifest.xml的theme
一、Activity 基础概念
Activity 是 Android 应用的核心组件之一,它代表一个单一的、用户可交互的屏幕。Activity可以理解成一个绘制用户界面的窗口, 而这个窗口可以填满整个屏幕,也可能比屏幕小或者浮动在其他窗口的上方!
注意:必须在 AndroidManifest.xml 文件中进行声明。
二、Activity 生命周期
这是 Activity 最核心的概念,它描述了 Activity 从创建到销毁的整个过程。系统通过调用一系列生命周期回调方法来管理 Activity。
1. 生命周期回调方法
onCreate():必须实现。Activity 第一次创建时调用。在此进行一次性初始化,如加载布局 (setContentView)、绑定数据等。
onStart():Activity 对用户可见之前调用。此时 Activity 已进入前台,但可能还无法与用户交互(例如被一个对话框部分覆盖)。
onResume():Activity 开始与用户交互之前调用。此时 Activity 位于 Activity 堆栈的顶部,接收用户输入。应用的核心功能通常在这里恢复。
onPause():当系统准备启动或恢复另一个 Activity 时调用。在此应提交未保存的更改、释放占用资源的系统组件(如广播接收器),但操作要轻量快速,否则会拖慢下一个 Activity 的启动。
onStop():Activity 对用户完全不可见时调用。可以执行重量级的关闭操作,如将数据写入数据库。
onRestart():在onStop()之后,Activity 重新启动时调用,后接onStart()。
onDestroy():Activity被销毁之前调用。这是 Activity 收到的最后一个回调。可能是因为 Activity 正常结束,也可能是因为系统为节省空间而将其销毁。

2. 生命周期场景
正常启动:A onCreate -> A onStart -> A onResume
打开新 Activity B(A 完全被覆盖):A onPause -> B onCreate -> B onStart -> B onResume -> A onStop
从 B 返回 A:B onPause -> A onRestart -> A onStart -> A onResume -> B onStop -> B onDestroy
按返回键退出 A:A onPause -> A onStop -> A onDestroy
屏幕旋转/配置更改:当前 Activity 会被销毁并重建。A onPause -> A onStop -> A onDestroy -> A onCreate -> A onStart -> A onResume
另外AlertDialog和PopWindow是不会触发onPause(),onStop()回调方法!!!
AlertDialog和PopupWindow默认不会触发其所属 Activity 的onPause()和onStop()回调。 这是因为它们被系统归类为同一窗口内部的UI元素,而不是一个新的、独立的“用户界面”。它们附着在所属 Activity 的窗口之上。它们与 Activity 共享同一个 “UI上下文” 和 “焦点栈”。
触发或不触发 onPause/onStop 的 UI 组件(本质是附属的还是独立的)
| 组件类型 | 默认行为 | 原因 |
|---|---|---|
| Activity | 触发下层 Activity 的 onPause/onStop | 创建了新的顶级窗口,抢夺了焦点和可见性。 |
| AlertDialog, PopupWindow, DialogFragment | 不触发 onPause/onStop | 是附属窗口,与 Activity 共享同一UI上下文和焦点栈。 |
| Spinner, Menu, Snackbar, Toast | 不触发 onPause/onStop | 属于应用内弹出的临时UI,本质是 PopupWindow 或系统提示。 |
| 配置为系统悬浮窗的 PopupWindow | 触发 onPause/onStop | 窗口类型改变为 TYPE_SYSTEM_ALERT 等,成为独立的顶级窗口。 |
三、Activity / ActionBarActivity / AppCompatActivity的区别:
Activity:是 Android 框架原始的、最基础的基类。
ActionBarActivity:是 过时 的 Support Library 类,用于在旧版 Android 上实现 Material Design 风格的 ActionBar。
AppCompatActivity:是 现代、官方推荐 的 Support Library / AndroidX 类,用于在旧版 Android 上实现 Material Design 及其最新特性,是ActionBarActivity的直接替代品。
简单来说,它们的演进路径是:Activity -> ActionBarActivity (已废弃) -> AppCompatActivity (当前标准)。
下面我们通过一个表格和详细解释来说明三者的区别。
| 特性 | Activity (原生) | ActionBarActivity (已废弃) | AppCompatActivity (现代) |
|---|---|---|---|
| 所属库 | android.app.Activity (Android Framework) | android.support.v7.app.ActionBarActivity (Old Support Library) | android.support.v7.app.AppCompatActivity (Old Support Lib)或 androidx.appcompat.app.AppCompatActivity (AndroidX) |
| 引入目的 | 提供基本的 Activity 组件功能。 | 在 Android 3.0 (API 11) 之前版本上提供 ActionBar 兼容支持。 | 提供更全面的 Material Design 特性向后兼容,并成为应用的基础类。 |
| ActionBar | API 11+ 原生支持。 | 主要功能:在低版本上提供 ActionBar。 | 提供并增强了 ActionBar 支持,并演变为 Toolbar 的官方支持载体。 |
| Material Design | API 21+ 原生支持。 | 有限的 Material Design 样式。 | 完整支持:将 Material Design 样式和组件(如 Toolbar)向后兼容到 API 7+。 |
| 主题要求 | 可以使用任何主题,如 Theme.Material。 | 必须使用/继承 Theme.AppCompat 系列主题。 | 必须使用/继承 Theme.AppCompat 系列主题。 |
| 现状与建议 | 仍在使用,但对于需要 Material Design 一致性的应用不推荐。 | 完全废弃。不应在新项目中使用,老项目应迁移。 | 官方强烈推荐 和 现代开发的标准选择。 |
“为了兼容低版本” 是 AppCompatActivity 最核心、最根本的设计目标和存在意义。
四、onCreate()一个参数和两个参数的区别:
-
onCreate(Bundle savedInstanceState):这是你最常见、必须实现的标准生命周期方法。即使两个参数的onCreate()实现了,也需要实现onCreate(Bundle savedInstanceState)。 -
onCreate(Bundle savedInstanceState, PersistableBundle persistentState):这是一个可选的重载方法,用于支持 “持久性” 的 Activity,允许它在设备重启后仍能恢复状态。在实际开发中极少使用。
详细对比分析
| 特性 | onCreate(Bundle savedInstanceState) | onCreate(Bundle savedInstanceState, PersistableBundle persistentState) |
|---|---|---|
| 方法签名 | 一个参数 | 两个参数 |
| API 级别 | 从 API 1 开始存在 | 从 API 21 (Android 5.0) 开始引入 |
| 使用场景 | 所有 Activity 的标准入口点。用于处理常规的初始化,如设置布局、绑定数据。 | 仅用于声明了 android:persistableMode="persistAcrossReboots" 的 Activity。 |
| 数据恢复范围 | 恢复因 配置变更 或 系统资源紧张被杀死 时的临时状态。 | 除了恢复上述状态,还能恢复在 设备关机再开机(重启) 后的持久状态。 |
| 数据持久性 | 临时性。数据保存在内存中,系统杀死进程后,这些数据就丢失了。 | 持久性。数据会写入磁盘,即使设备重启,数据依然存在。 |
| 适用情况 | 绝大多数应用场景。如恢复编辑框的文本、列表的滚动位置等。 | 极少数特殊场景。如系统设置、Launcher、或需要记录用户操作流程且不怕重启的应用。 |
| 如何保存数据 | 在 onSaveInstanceState(Bundle outState) 中保存数据。 | 除了 onSaveInstanceState,还需要在 onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) 中保存持久化数据。 |
1.单参数代码示例
@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);EditText editText = findViewById(R.id.editText);// 检查是否有之前保存的状态需要恢复if (savedInstanceState != null) {String savedText = savedInstanceState.getString("KEY_EDIT_TEXT");editText.setText(savedText);}
}// 必须重写此方法来保存临时状态
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {super.onSaveInstanceState(outState);outState.putString("KEY_EDIT_TEXT", editText.getText().toString());
}
2.双参数代码示例
要使用这个重载方法,你必须先在 AndroidManifest.xml 中为该 Activity 声明一个属性
<activityandroid:name=".MyPersistableActivity"android:persistableMode="persistAcrossReboots" />
两个 Bundle 参数的区别
-
savedInstanceState:和单参数版本一样,用于存储临时性状态。 -
persistentState:这是一个PersistableBundle对象,用于存储持久性状态。这个状态会被写入磁盘的/data/system/procstats目录下,即使设备关机再开机,这个数据依然存在。
// 在 AndroidManifest.xml 中声明了 android:persistableMode="persistAcrossReboots"
public class MyPersistableActivity extends AppCompatActivity {private int mPersistentCounter = 0;@Overridepublic void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {super.onCreate(savedInstanceState, persistentState);setContentView(R.layout.activity_persistable);// 从 persistentState 中恢复持久化数据if (persistentState != null) {mPersistentCounter = persistentState.getInt("PERSISTENT_COUNTER", 0);}Button button = findViewById(R.id.button);button.setOnClickListener(v -> {mPersistentCounter++;// 持久化数据不会自动保存,需要手动触发// 通常会在 onPause 或 onStop 中调用 onSaveInstanceState});}// 重写此方法来保存持久化数据@Overridepublic void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {super.onSaveInstanceState(outState, outPersistentState);// 将需要持久化的数据存入 outPersistentStateoutPersistentState.putInt("PERSISTENT_COUNTER", mPersistentCounter);}
}
单参数的 onCreate 是用来“恢复现场”的,而双参数的 onCreate 是用来“时光倒流”的。
五、Activity间的数据相互传递
传递:A-->B

在使用Bundle传递数据时,要注意,Bundle的大小是有限制的 < 0.5MB,如果大于这个值 是会报TransactionTooLargeException异常的!!!
传回:A<--B

这个在之前的 Intent 章节提到过,相关内容可以查看上一章。
六、关闭所有Activity和退出App
1.关闭所有Activity
有时我们可能会打开了很多个Activity,突然来个这样的需求,在某个页面可以关掉 所有的Activity并退出程序!好吧,下面提供一个关闭所有Activity的方法, 就是用一个list集合来存储所有Activity。

public class ActivityCollector { public static LinkedList<Activity> activities = new LinkedList<Activity>(); public static void addActivity(Activity activity) { activities.add(activity); } public static void removeActivity(Activity activity) { activities.remove(activity); } public static void finishAll() { for(Activity activity:activities) { if(!activity.isFinishing()) { activity.finish(); } } }
}
2.退出App
/** * 退出应用程序 */
public void AppExit(Context context) { try { ActivityCollector.finishAll(); //暴力杀死后台进程 ActivityManager activityMgr = (ActivityManager) context .getSystemService(Context.ACTIVITY_SERVICE); activityMgr.killBackgroundProcesses(context.getPackageName()); System.exit(0); } catch (Exception ignored) {}
}
调用 killBackgroundProcesses() 方法,传入当前应用的包名,强制杀死该应用的所有后台进程。
七、屏幕旋转对Activity的影响
屏幕旋转是 配置变更 中最典型的例子,当发生旋转后会销毁与重建。
出现的问题:
- Activity 中所有非持久化的成员变量和数据都会丢失,因为对象被销毁了。
- 用户体验中断:正在播放的视频、动画会中断,滚动列表的位置会重置,输入框的焦点会丢失等。
1.使用 onSaveInstanceState() 保存临时状态(最常用)
这是最基本也是必须掌握的方案。系统在销毁 Activity之前会调用此方法,让你有机会保存临时状态。
//保存状态
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {super.onSaveInstanceState(outState); // 必须调用父类方法!// 将需要恢复的数据存入BundleoutState.putInt("KEY_SCORE", mCurrentScore);outState.putString("KEY_INPUT_TEXT", mUserInputText);
}//恢复状态
@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 检查是否有之前保存的状态if (savedInstanceState != null) {mCurrentScore = savedInstanceState.getInt("KEY_SCORE", 0);mUserInputText = savedInstanceState.getString("KEY_INPUT_TEXT", "");// 恢复UI状态,比如设置EditText的文本EditText editText = findViewById(R.id.editText);editText.setText(mUserInputText);}
}
注意: onSaveInstanceState 主要用于保存轻量级的、瞬时的 UI 状态。不适合保存大量数据(如Bitmap)或需要持久化的数据。
2.手动处理配置变更(阻止销毁重建)
你可以告知系统:“这个配置变更由我自己处理,你不要销毁我的 Activity”。
在 AndroidManifest.xml 中为 Activity 配置 android:configChanges 属性。
<activityandroid:name=".MainActivity"android:configChanges="orientation|screenSize|keyboardHidden" />
orientation:屏幕方向
screenSize:屏幕尺寸(API 13以上必需,因为旋转也涉及尺寸变化)
keyboardHidden:键盘可用性改变
效果:
-
设置之后,屏幕旋转时 Activity 不会被销毁重建。
-
取而代之,系统会调用
onConfigurationChanged(Configuration newConfig)方法。
@Override
public void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {// 切换到横屏,可以在这里手动调整UILog.d("Orientation", "Now in Landscape");} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {// 切换到竖屏Log.d("Orientation", "Now in Portrait");}
}
优缺点:
-
优点:Activity 不会重建,所有成员变量都得以保留,用户体验无缝。
-
缺点:
-
你必须自己处理所有UI更新。例如,如果你为横竖屏准备了不同的布局(
layout-land和layout-port),系统不会自动切换,你需要手动调用setContentView并重新初始化所有视图,这非常繁琐且容易出错。 -
不推荐作为常规解决方案,仅适用于确实不希望UI被重建的特殊场景(如游戏、摄像头预览)。假如在特定场景下使用,如打开后必须使用横屏/竖屏。我们就可以看看下面的方法。
-
3.固定 Activity 屏幕方向的方法
3.1 在 AndroidManifest.xml 中配置(推荐)
这是最常用、最简洁的方式,在应用清单文件中为 Activity 声明屏幕方向。
<activityandroid:name=".MainActivity"android:screenOrientation="portrait" /> <!-- 固定为竖屏 --><activityandroid:name=".MainActivity"android:screenOrientation="landscape" /> <!-- 固定为横屏 -->
3.2 在 Java 代码中动态设置
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 固定为竖屏setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);// 或者固定为横屏// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);setContentView(R.layout.activity_main);}
}
4.使用 ViewModel + LiveData(架构组件推荐)
这是 现代 Android 开发中最推荐、最优雅的解决方案。ViewModel 的设计目的就是存放和管理与UI相关的数据,并且它的生命周期比 Activity 更长。
ViewModel 在配置变更(如旋转)中会存活下来!
// 1. 创建ViewModel
public class MyViewModel extends ViewModel {private MutableLiveData<Integer> currentScore = new MutableLiveData<>(0);private MutableLiveData<String> userInput = new MutableLiveData<>("");public LiveData<Integer> getCurrentScore() {return currentScore;}public void setScore(int score) {currentScore.setValue(score);}public LiveData<String> getUserInput() {return userInput;}public void setUserInput(String input) {userInput.setValue(input);}
}// 2. 在Activity中使用
public class MainActivity extends AppCompatActivity {private MyViewModel viewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 获取ViewModel(如果是旋转后重建,会拿到同一个实例)viewModel = new ViewModelProvider(this).get(MyViewModel.class);// 观察LiveData,数据变化时自动更新UIviewModel.getCurrentScore().observe(this, score -> {TextView scoreView = findViewById(R.id.scoreView);scoreView.setText("Score: " + score);});viewModel.getUserInput().observe(this, input -> {EditText editText = findViewById(R.id.editText);if (!editText.getText().toString().equals(input)) {editText.setText(input);}});findViewById(R.id.button).setOnClickListener(v -> {// 更新ViewModel中的数据,观察者会自动触发UI更新viewModel.setScore(viewModel.getCurrentScore().getValue() + 1);});}
}
优势:
-
数据与UI分离:Activity 只负责显示和交互,数据由
ViewModel持有。 -
自动生命周期管理:无需手动保存和恢复,代码更简洁。
-
完美的数据持久性:屏幕旋转对用户完全无感,数据一直都在。
与其他方案的对比
| 方案 | 适用场景 | 实现复杂度 | 用户体验 |
|---|---|---|---|
| 固定屏幕方向 | 不需要横竖屏切换的应用 | ⭐☆☆☆☆ (非常简单) | 一致但不够灵活 |
| onSaveInstanceState | 需要保存简单状态的应用 | ⭐⭐☆☆☆ (简单) | 有短暂的中断 |
| ViewModel | 现代应用,数据驱动的UI | ⭐⭐⭐☆☆ (中等) | 几乎无缝 |
| configChanges | 特殊场景,如游戏、相机 | ⭐⭐⭐⭐☆ (复杂) | 完全无缝 |
八、启动模式
接下来我们来详细地讲解下四种加载模式: 他们分别是:standard(默认),singleTop,singleTask,singleInstance
在 AndroidManifest.xml 中通过 android:launchMode 设置。

standard(默认):每次启动都会创建一个新的 Activity 实例。一个任务中可以有多个相同 Activity 的实例。
singleTop:如果要启动的 Activity 已经位于任务栈顶,则不会创建新实例,而是调用其onNewIntent()方法。否则创建新实例。适用于防止重复启动同一个界面(如通知点击)。
singleTask:系统会创建一个新任务,并将该 Activity 实例化为新任务的根 Activity。如果该 Activity 的实例已存在于一个独立的任务中,系统会将该任务转到前台,并调用onNewIntent()。一个任务中只存在一个该 Activity 的实例。常用于应用的主页。
singleInstance:与singleTask类似,但持有该 Activity 的任务只能有这一个 Activity。任何从该 Activity 启动的新 Activity 都会在另一个任务中打开。适用于需要单独任务栈的场景(如闹钟)。
使用 Intent Flag 动态控制:
你也可以在 Intent 中设置 Flag 来动态控制启动行为,其优先级高于 launchMode。
-
FLAG_ACTIVITY_NEW_TASK:在新任务中启动 Activity。 -
FLAG_ACTIVITY_SINGLE_TOP:等同于singleTop。 -
FLAG_ACTIVITY_CLEAR_TOP:如果目标 Activity 已在当前任务中,则会销毁位于它之上的所有 Activity,使其位于栈顶。
九、设置Activity全屏的方法
1.代码隐藏ActionBar
在Activity的onCreate方法中调用getActionBar.hide();即可
2.通过requestWindowFeature设置
requestWindowFeature(Window.FEATURE_NO_TITLE); 该代码需要在setContentView ()之前调用,不然会报错!!!
注: 把 requestWindowFeature(Window.FEATURE_NO_TITLE);放在super.onCreate(savedInstanceState);前面就可以隐藏ActionBar而不报错。
3.通过AndroidManifest.xml的theme
在需要全屏的Activity的标签内设置 theme = @android:style/Theme.NoTitleBar.FullScreen
