Activity生命周期与启动模式(一):基础概念与生命周期
本文是Android四大组件系列的第一篇,主要介绍Activity的基本概念、生命周期以及实际应用场景。
一、Activity简介
Activity是Android应用程序的核心组件之一,它提供了一个用户界面,让用户可以与应用程序进行交互。从用户体验的角度来看,Activity就像是应用程序的"窗口"或"页面"。一个Android应用通常由多个Activity组成,它们之间可以相互跳转,共同构成了应用的用户界面流程。
1.1 Activity的作用
- 提供用户界面:Activity是用户与应用交互的主要入口
- 管理用户输入:处理屏幕触摸、键盘输入等用户操作
- 处理应用逻辑:响应用户操作,执行相应的业务逻辑
- 协调应用组件:与其他组件(如Service、BroadcastReceiver等)进行交互
1.2 Activity的基本使用
要创建一个Activity,需要完成以下步骤:
- 创建一个类继承自
Activity
或其子类(如AppCompatActivity
) - 实现必要的生命周期方法,如
onCreate()
- 在
AndroidManifest.xml
中声明该Activity
// 1. 创建Activity类
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 设置布局文件
setContentView(R.layout.activity_main);
// 初始化视图、设置监听器等
Button btnStart = findViewById(R.id.btn_start);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 启动另一个Activity
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
}
<!-- 2. 在AndroidManifest.xml中声明Activity -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity" />
</application>
</manifest>
二、Activity生命周期
2.1 生命周期概述
Activity的生命周期是指从创建到销毁的整个过程,Android系统通过一系列回调方法来管理Activity的生命周期。了解这些生命周期方法对于开发高质量的Android应用至关重要。
主要的生命周期方法包括:
- onCreate():Activity创建时调用
- onStart():Activity变为可见时调用
- onResume():Activity获取焦点,可与用户交互时调用
- onPause():Activity失去焦点,但仍部分可见时调用
- onStop():Activity完全不可见时调用
- onRestart():Activity从停止状态重新变为可见前调用
- onDestroy():Activity被销毁前调用
2.2 生命周期方法详解
onCreate()
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("LifeCycle", "onCreate called");
// 初始化操作:获取Intent数据、初始化视图、绑定数据等
if (savedInstanceState != null) {
// 恢复之前保存的状态
String savedText = savedInstanceState.getString("saved_text");
// 使用恢复的数据
}
}
适合做的事情:
- 设置布局(setContentView)
- 初始化视图组件
- 绑定数据
- 创建长期运行的组件(如线程)
- 恢复保存的状态
注意事项:
- 这里的操作应尽量轻量级,避免耗时操作
- 不要在这里请求运行时权限,应在视图完全显示后请求
onStart()
@Override
protected void onStart() {
super.onStart();
Log.d("LifeCycle", "onStart called");
// Activity变为可见,但用户还不能与之交互
}
适合做的事情:
- 注册需要在Activity可见时监听的广播接收器
- 启动只在Activity可见时需要运行的服务
onResume()
@Override
protected void onResume() {
super.onResume();
Log.d("LifeCycle", "onResume called");
// Activity获取焦点,用户可以与之交互
// 启动需要在前台运行的功能,如动画、相机预览等
}
适合做的事情:
- 启动需要用户交互的功能(如相机、传感器、动画)
- 恢复在onPause()中暂停的操作
- 初始化在其他Activity可能修改的组件
onPause()
@Override
protected void onPause() {
// 暂停或释放在onResume中启动的资源
// 保存关键数据,但要快速执行(不到1秒)
Log.d("LifeCycle", "onPause called");
super.onPause();
}
适合做的事情:
- 暂停消耗CPU的操作
- 暂停媒体播放
- 释放系统资源(如相机、传感器)
- 保存未保存的数据(但操作要快)
注意事项:
- 这个方法执行时间很短,不适合做耗时操作
- 不要在这里保存大量数据到数据库或网络
onStop()
@Override
protected void onStop() {
// Activity完全不可见,可以执行较重的关闭操作
Log.d("LifeCycle", "onStop called");
super.onStop();
}
适合做的事情:
- 执行CPU密集型关闭操作
- 保存用户数据到持久化存储
- 解注册广播接收器
- 释放资源
onRestart()
@Override
protected void onRestart() {
super.onRestart();
Log.d("LifeCycle", "onRestart called");
// Activity从停止状态重新变为可见前调用
// 之后会调用onStart()
}
适合做的事情:
- 准备Activity重新变为可见所需的特殊处理
onDestroy()
@Override
protected void onDestroy() {
// 释放所有资源,防止内存泄漏
Log.d("LifeCycle", "onDestroy called");
super.onDestroy();
}
适合做的事情:
- 释放所有资源
- 关闭数据库连接
- 注销监听器
- 销毁长期运行的后台任务
2.3 生命周期的完整示例
下面是一个完整的Activity生命周期示例,包含所有生命周期方法的实现和日志记录:
public class LifecycleDemoActivity extends AppCompatActivity {
private static final String TAG = "LifecycleDemoActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle_demo);
Log.d(TAG, "onCreate called");
Button nextButton = findViewById(R.id.btn_next);
nextButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 启动另一个Activity
Intent intent = new Intent(LifecycleDemoActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart called");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume called");
}
@Override
protected void onPause() {
Log.d(TAG, "onPause called");
super.onPause();
}
@Override
protected void onStop() {
Log.d(TAG, "onStop called");
super.onStop();
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart called");
}
@Override
protected void onDestroy() {
Log.d(TAG, "onDestroy called");
super.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
// 保存Activity状态
outState.putString("saved_text", "Some text to save");
Log.d(TAG, "onSaveInstanceState called");
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// 恢复Activity状态
String savedText = savedInstanceState.getString("saved_text");
Log.d(TAG, "onRestoreInstanceState called: " + savedText);
}
}
三、Activity状态保存与恢复
在Android系统中,当配置发生变化(如屏幕旋转)或系统内存不足时,Activity可能会被销毁并重新创建。为了提供良好的用户体验,我们需要保存和恢复Activity的状态。
3.1 onSaveInstanceState() 与 onRestoreInstanceState()
@Override
protected void onSaveInstanceState(Bundle outState) {
// 保存视图状态
EditText editText = findViewById(R.id.edit_text);
outState.putString("input_text", editText.getText().toString());
// 保存自定义数据
outState.putInt("counter", mCounter);
outState.putParcelable("user_data", mUserData);
Log.d(TAG, "onSaveInstanceState called");
super.onSaveInstanceState(outState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// 恢复视图状态
String inputText = savedInstanceState.getString("input_text");
EditText editText = findViewById(R.id.edit_text);
editText.setText(inputText);
// 恢复自定义数据
mCounter = savedInstanceState.getInt("counter");
mUserData = savedInstanceState.getParcelable("user_data");
Log.d(TAG, "onRestoreInstanceState called");
}
3.2 ViewModel的使用
Android Jetpack提供了ViewModel组件,它可以在配置变化时保存数据,避免重复加载:
// 定义ViewModel
public class MainViewModel extends ViewModel {
private MutableLiveData<Integer> counter = new MutableLiveData<>();
public MainViewModel() {
counter.setValue(0);
}
public LiveData<Integer> getCounter() {
return counter;
}
public void incrementCounter() {
counter.setValue(counter.getValue() + 1);
}
@Override
protected void onCleared() {
super.onCleared();
// 清理资源
}
}
// 在Activity中使用ViewModel
public class MainActivity extends AppCompatActivity {
private MainViewModel viewModel;
private TextView counterText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取ViewModel实例
viewModel = new ViewModelProvider(this).get(MainViewModel.class);
counterText = findViewById(R.id.counter_text);
Button incrementButton = findViewById(R.id.increment_button);
// 观察LiveData变化
viewModel.getCounter().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer count) {
counterText.setText(String.valueOf(count));
}
});
incrementButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
viewModel.incrementCounter();
}
});
}
}
四、实战案例:Activity生命周期监控
在实际开发中,了解Activity的生命周期状态对于调试和性能优化非常重要。下面我们将实现一个Activity生命周期监控工具。
4.1 创建生命周期监控基类
public abstract class BaseActivity extends AppCompatActivity {
private static final String TAG = "ActivityLifecycle";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, getClass().getSimpleName() + " - onCreate");
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, getClass().getSimpleName() + " - onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, getClass().getSimpleName() + " - onResume");
}
@Override
protected void onPause() {
Log.d(TAG, getClass().getSimpleName() + " - onPause");
super.onPause();
}
@Override
protected void onStop() {
Log.d(TAG, getClass().getSimpleName() + " - onStop");
super.onStop();
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, getClass().getSimpleName() + " - onRestart");
}
@Override
protected void onDestroy() {
Log.d(TAG, getClass().getSimpleName() + " - onDestroy");
super.onDestroy();
}
}
4.2 使用Lifecycle组件监控生命周期
Android Jetpack提供了Lifecycle组件,可以更方便地监控Activity的生命周期:
public class MyLifecycleObserver implements LifecycleObserver {
private static final String TAG = "MyLifecycleObserver";
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate() {
Log.d(TAG, "ON_CREATE");
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
Log.d(TAG, "ON_START");
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
Log.d(TAG, "ON_RESUME");
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
Log.d(TAG, "ON_PAUSE");
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop() {
Log.d(TAG, "ON_STOP");
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy() {
Log.d(TAG, "ON_DESTROY");
}
}
// 在Activity中使用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 添加生命周期观察者
getLifecycle().addObserver(new MyLifecycleObserver());
}
}
4.3 调试技巧:使用Fragment监控Activity生命周期
可以创建一个无UI的Fragment来监控Activity的生命周期,这在复杂应用中特别有用:
public class LifecycleLoggerFragment extends Fragment {
private static final String TAG = "LifecycleLogger";
private String activityName;
public static LifecycleLoggerFragment newInstance(String activityName) {
LifecycleLoggerFragment fragment = new LifecycleLoggerFragment();
Bundle args = new Bundle();
args.putString("activity_name", activityName);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true); // 在配置变化时保留实例
activityName = getArguments().getString("activity_name");
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
Log.d(TAG, activityName + " - onAttach");
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.d(TAG, activityName + " - onActivityCreated");
}
// 其他生命周期方法...
}
// 在Activity中使用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 添加生命周期监控Fragment
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.add(LifecycleLoggerFragment.newInstance(getClass().getSimpleName()), "logger")
.commit();
}
}
}
五、常见面试题解析
5.1 Activity生命周期相关面试题
问题1:描述Activity的完整生命周期
答案:Activity的完整生命周期包括以下阶段:
- 完整生命周期:从onCreate()到onDestroy(),这期间Activity被创建、显示、隐藏直至销毁。
- 可见生命周期:从onStart()到onStop(),这期间Activity对用户可见,但可能没有焦点。
- 前台生命周期:从onResume()到onPause(),这期间Activity在前台并与用户交互。
问题2:为什么要在onPause()中保存数据而不是onStop()?
答案:
- onPause()方法一定会被调用,而在极端情况下(如内存不足),系统可能会直接杀死Activity而不调用onStop()和onDestroy()。
- 但需注意onPause()执行时间很短(不到1秒),所以只适合做轻量级的保存操作,复杂的持久化操作应放在onStop()中。
问题3:屏幕旋转时Activity的生命周期变化是什么?如何保持数据?
答案:
- 屏幕旋转时,默认情况下Activity会被销毁并重新创建,生命周期流程为:onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()
- 保持数据的方法有:
- 使用onSaveInstanceState()和onRestoreInstanceState()保存和恢复数据
- 使用ViewModel组件,它在配置变化时不会被销毁
- 在AndroidManifest中设置android:configChanges=“orientation|screenSize”,阻止Activity重建
- 使用Fragment的setRetainInstance(true)
问题4:onSaveInstanceState()和onRestoreInstanceState()调用时机是什么?
答案:
- onSaveInstanceState()在Activity可能被销毁前调用,通常在onStop()之前,但不一定在onPause()之后。
- onRestoreInstanceState()在onCreate()之后调用,但只有在有状态需要恢复时才会被调用。
- onCreate()方法也可以从savedInstanceState参数恢复状态,区别是onRestoreInstanceState()一定有非空的Bundle参数。
问题5:如何避免Activity重建时的闪烁问题?
答案:
- 在主题中设置windowDisablePreview属性
- 使用android:configChanges="orientation|screenSize"阻止重建
- 优化布局加载速度,减少onCreate()中的耗时操作
- 使用Transition框架实现平滑过渡
5.2 实际开发中的生命周期问题
问题1:如何处理Activity被系统回收后的数据恢复问题?
答案:
- 使用onSaveInstanceState()保存关键数据
- 使用ViewModel存储UI相关数据
- 对于大量数据,考虑使用持久化存储(如Room数据库)
- 使用单例或Application级别的缓存
- 实现Parcelable接口优化序列化性能
问题2:如何解决Activity内存泄漏问题?
答案:
- 避免在Activity中使用静态变量引用Activity或Context
- 正确处理内部类和匿名类,使用弱引用或静态内部类+弱引用
- 在onDestroy()中取消异步任务和注销监听器
- 使用LeakCanary等工具检测内存泄漏
- 避免在生命周期方法外持有View引用
六、开源项目实战分析
6.1 分析LeakCanary中的Activity生命周期监控
LeakCanary是一个内存泄漏检测库,它通过监控Activity的生命周期来检测潜在的内存泄漏。
// LeakCanary中的ActivityLifecycleCallbacks实现(简化版)
public class ActivityLifecycleMonitor implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
// 记录Activity创建
}
@Override
public void onActivityDestroyed(Activity activity) {
// 当Activity销毁时,检查是否存在内存泄漏
// 通过弱引用和引用队列检测Activity是否被正确回收
watchForLeak(activity);
}
private void watchForLeak(Activity activity) {
// 创建弱引用并关联引用队列
// 延迟检查Activity是否被回收
// 如果没有被回收,触发堆转储并分析泄漏路径
}
// 其他生命周期回调方法...
}
6.2 分析Glide中的生命周期管理
Glide是一个流行的图片加载库,它会根据Activity/Fragment的生命周期自动管理图片加载任务。
// Glide中的生命周期监听(简化版)
public class RequestManager implements LifecycleListener {
public RequestManager(Lifecycle lifecycle) {
// 注册生命周期监听
lifecycle.addListener(this);
}
@Override
public void onStart() {
// 恢复暂停的请求
resumeRequests();
}
@Override
public void onStop() {
// 暂停请求,释放资源
pauseRequests();
}
@Override
public void onDestroy() {
// 清理资源,取消请求
clearRequests();
}
}
总结
本文详细介绍了Activity的基本概念和生命周期,包括各个生命周期方法的调用时机和适合执行的操作。我们还学习了如何保存和恢复Activity状态,以及使用ViewModel等现代组件简化状态管理。通过实战案例和开源项目分析,我们了解了如何在实际开发中应用这些知识。