Activity 作为 Android 应用的核心组件之一,承载了用户界面的展示和交互功能。本文将全面深入地探讨 Activity 的使用方法,涵盖生命周期管理、启动模式、数据传递、状态保存等关键知识点,并结合实际代码示例进行讲解。
一、Activity 基础概念
1.1 什么是 Activity?
Activity 是 Android 四大组件之一,它代表一个单一的屏幕界面,类似于桌面应用程序中的窗口。每个 Activity 都提供一个用户界面,用户可以通过这个界面与应用进行交互。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
1.2 Activity 的基本结构
一个标准的 Activity 通常包含以下要素:
- 继承自
AppCompatActivity
或Activity
onCreate()
方法用于初始化setContentView()
设置布局文件- 在 AndroidManifest.xml 中注册
二、Activity 生命周期详解
理解 Activity 生命周期是开发稳定应用的关键。以下是完整的生命周期方法:
2.1 完整生命周期方法
public class LifecycleDemoActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle);
Log.d("Lifecycle", "onCreate");
}
@Override
protected void onStart() {
super.onStart();
Log.d("Lifecycle", "onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d("Lifecycle", "onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d("Lifecycle", "onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d("Lifecycle", "onStop");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d("Lifecycle", "onRestart");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d("Lifecycle", "onDestroy");
}
}
2.2 生命周期状态转换图
启动Activity → onCreate → onStart → onResume → 运行状态
运行状态 → 按下Home键 → onPause → onStop → 停止状态
停止状态 → 返回应用 → onRestart → onStart → onResume → 运行状态
运行状态 → 按下返回键 → onPause → onStop → onDestroy → 销毁状态
2.3 实际应用场景
- onCreate():初始化UI、绑定数据、创建线程或AsyncTask
- onResume():启动动画、注册广播接收器、恢复暂停的操作
- onPause():保存数据、停止动画、注销广播接收器
- onDestroy():释放资源、取消网络请求
三、Activity 的启动与传参
3.1 显式启动 Activity
// 启动标准Activity
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
// 启动带返回结果的Activity
Intent intent = new Intent(MainActivity.this, PickContactActivity.class);
startActivityForResult(intent, REQUEST_CODE_PICK_CONTACT);
3.2 隐式启动 Activity
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.example.com"));
startActivity(intent);
在 AndroidManifest.xml 中配置 intent-filter:
<activity android:name=".BrowserActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
3.3 数据传递方式
3.3.1 使用 Intent 传递基本数据
// 发送数据
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("USER_ID", 123);
intent.putExtra("USER_NAME", "John Doe");
startActivity(intent);
// 接收数据
int userId = getIntent().getIntExtra("USER_ID", 0);
String userName = getIntent().getStringExtra("USER_NAME");
3.3.2 使用 Bundle 传递复杂数据
// 发送数据
Bundle bundle = new Bundle();
bundle.putSerializable("USER", userObject);
intent.putExtras(bundle);
// 接收数据
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
User user = (User) bundle.getSerializable("USER");
}
3.3.3 使用 Parcelable 传递对象
public class User implements Parcelable {
private String name;
private int age;
// 实现Parcelable接口的方法
protected User(Parcel in) {
name = in.readString();
age = in.readInt();
}
public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel in) {
return new User(in);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(age);
}
}
// 使用
User user = new User("John", 25);
intent.putExtra("USER", user);
3.4 处理返回结果
// 启动Activity时
startActivityForResult(intent, REQUEST_CODE);
// 在源Activity中重写onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
if (resultCode == RESULT_OK) {
String result = data.getStringExtra("RESULT");
// 处理返回结果
}
}
}
// 在目标Activity中设置返回结果
Intent resultIntent = new Intent();
resultIntent.putExtra("RESULT", "Some result data");
setResult(RESULT_OK, resultIntent);
finish();
四、Activity 启动模式详解
Activity 的启动模式决定了 Activity 的实例如何与任务栈交互。
4.1 四种启动模式
4.1.1 standard(标准模式)
默认模式,每次启动都会创建新的实例。
<activity android:name=".StandardActivity"
android:launchMode="standard" />
4.1.2 singleTop(栈顶复用)
如果 Activity 已经在栈顶,则不会创建新实例,而是调用 onNewIntent()
。
<activity android:name=".SingleTopActivity"
android:launchMode="singleTop" />
4.1.3 singleTask(栈内复用)
系统会检查是否存在该 Activity 的任务栈,如果存在则直接复用,并清除其上所有 Activity。
<activity android:name=".SingleTaskActivity"
android:launchMode="singleTask" />
4.1.4 singleInstance(单实例模式)
单独位于一个任务栈中,且该任务栈只包含这一个 Activity。
<activity android:name=".SingleInstanceActivity"
android:launchMode="singleInstance" />
4.2 Intent Flags 控制启动行为
除了在 manifest 中设置,还可以通过 Intent Flags 动态控制:
Intent intent = new Intent(this, SomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 类似singleTask
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); // 类似singleTop
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // 清除栈顶Activity
startActivity(intent);
4.3 任务栈(Task Affinity)
通过 taskAffinity
属性可以指定 Activity 的任务栈:
<activity android:name=".TaskAffinityActivity"
android:taskAffinity="com.example.customtask" />
五、Activity 状态保存与恢复
5.1 临时状态保存
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("KEY", "Value");
outState.putInt("COUNT", count);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
String value = savedInstanceState.getString("KEY");
int count = savedInstanceState.getInt("COUNT");
}
5.2 永久数据保存
对于需要持久化的数据,应该使用 SharedPreferences、数据库或文件存储:
@Override
protected void onPause() {
super.onPause();
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("AUTO_SAVE", autoSaveData);
editor.apply();
}
@Override
protected void onResume() {
super.onResume();
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
String autoSaveData = prefs.getString("AUTO_SAVE", "");
}
六、Activity 高级主题
6.1 透明 Activity
创建透明背景的 Activity:
<style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
</style>
在 AndroidManifest.xml 中应用主题:
<activity android:name=".TransparentActivity"
android:theme="@style/Theme.Transparent" />
6.2 Activity 转场动画
6.2.1 传统方式
// 启动Activity时
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
// 结束Activity时
finish();
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
6.2.2 使用 ActivityOptions (API 21+)
// 共享元素转场
ActivityOptions options = ActivityOptions
.makeSceneTransitionAnimation(this, view, "transitionName");
startActivity(intent, options.toBundle());
6.3 多窗口模式支持
Android 7.0 引入了多窗口模式,需要适配:
<activity android:name=".MultiWindowActivity"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" />
处理配置变化:
@Override
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
super.onMultiWindowModeChanged(isInMultiWindowMode);
// 调整UI布局
}
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode);
// 调整UI布局
}
七、常见问题与最佳实践
7.1 内存泄漏预防
- 避免在 Activity 中持有静态引用
- 及时注销广播接收器、监听器等
- 使用 WeakReference 持有 Context 引用
- 避免在非UI线程持有 Activity 引用
7.2 性能优化建议
- 减少 onCreate() 中的耗时操作
- 使用 ViewStub 延迟加载不常用的布局
- 合理使用 ViewModel 保存 UI 数据
- 考虑使用 Fragment 代替多个 Activity
7.3 常见问题解决
问题1:Activity 被意外销毁后重建导致数据丢失
解决方案:
- 使用 onSaveInstanceState() 保存临时状态
- 对于重要数据,使用 ViewModel + SavedStateHandle
- 实现 Parcelable 或 Serializable 接口保存复杂对象
问题2:启动模式不生效
解决方案:
- 检查 AndroidManifest.xml 中的 launchMode 设置
- 检查是否有 Intent Flags 覆盖了启动模式
- 使用 adb shell dumpsys activity activities 命令查看任务栈
八、实战案例:实现一个登录流程
public class LoginActivity extends AppCompatActivity {
private EditText etUsername, etPassword;
private Button btnLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
etUsername = findViewById(R.id.et_username);
etPassword = findViewById(R.id.et_password);
btnLogin = findViewById(R.id.btn_login);
btnLogin.setOnClickListener(v -> {
String username = etUsername.getText().toString();
String password = etPassword.getText().toString();
if (validateInput(username, password)) {
attemptLogin(username, password);
}
});
}
private boolean validateInput(String username, String password) {
// 验证输入有效性
return !username.isEmpty() && !password.isEmpty();
}
private void attemptLogin(String username, String password) {
// 显示加载进度条
showProgress(true);
// 模拟网络请求
new Handler().postDelayed(() -> {
showProgress(false);
if (loginSuccess(username, password)) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.putExtra("USERNAME", username);
startActivity(intent);
finish();
} else {
showError("Invalid credentials");
}
}, 2000);
}
private boolean loginSuccess(String username, String password) {
// 简单的模拟验证
return "admin".equals(username) && "123456".equals(password);
}
private void showProgress(boolean show) {
// 显示/隐藏进度条
}
private void showError(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
结语
Activity 作为 Android 开发的基石,掌握其使用方法和原理对于构建高质量应用至关重要。本文从基础到高级全面介绍了 Activity 的各个方面,希望读者能够通过实践加深理解。随着 Android 开发的演进,虽然出现了 Compose 等新的 UI 框架,但 Activity 仍然是应用架构中不可或缺的一部分。在实际开发中,建议结合 ViewModel、LiveData 等架构组件,构建更加健壮和可维护的应用。