12 KiB
12 KiB
Activity详解
目录
- Activity生命周期
- Activity启动模式
- Activity任务栈
- Activity与Fragment通信
- Activity重建
- Activity转场动画
- Activity最佳实践
- 面试常见问题
Activity生命周期
生命周期方法
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Activity 创建时调用
// 初始化视图、数据绑定
setContentView(R.layout.activity_main);
}
@Override
protected void onStart() {
super.onStart();
// Activity 可见但不可交互
// 注册广播、启动动画
}
@Override
protected void onResume() {
super.onResume();
// Activity 可见且可交互
// 恢复动画、开始数据更新
}
@Override
protected void onPause() {
super.onPause();
// Activity 失去焦点
// 暂停动画、保存数据
}
@Override
protected void onStop() {
super.onStop();
// Activity 不可见
// 停止动画、注销广播
}
@Override
protected void onDestroy() {
super.onDestroy();
// Activity 被销毁
// 释放资源、取消网络请求
}
@Override
protected void onRestart() {
super.onRestart();
// Activity 从 onStop 恢复
// 重新初始化
}
}
生命周期流程图
启动 Activity:
onCreate() → onStart() → onResume()
按 Home 键:
onPause() → onStop()
返回 Activity:
onRestart() → onStart() → onResume()
按 Back 键:
onPause() → onStop() → onDestroy()
屏幕旋转:
onPause() → onStop() → onDestroy()
→ onCreate() → onStart() → onResume()
生命周期场景
1. 正常启动和销毁
// 启动
onCreate() → onStart() → onResume()
// 销毁
onPause() → onStop() → onDestroy()
2. 切换到后台
// 按 Home 键
onPause() → onStop()
// 返回
onRestart() → onStart() → onResume()
3. 屏幕旋转
// 旋转前
onPause() → onStop() → onDestroy()
// 旋转后
onCreate() → onStart() → onResume()
Activity启动模式
四种启动模式
1. standard(标准模式)
<!-- AndroidManifest.xml -->
<activity
android:name=".MainActivity"
android:launchMode="standard" />
特点:
- 每次启动都创建新实例
- 可以多个实例存在
- 默认启动模式
// 示例
// 启动 MainActivity 3 次,会创建 3 个实例
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent); // 实例1
startActivity(intent); // 实例2
startActivity(intent); // 实例3
2. singleTop(栈顶复用)
<activity
android:name=".MainActivity"
android:launchMode="singleTop" />
特点:
- 如果 Activity 在栈顶,复用该实例
- 如果不在栈顶,创建新实例
- 适合防止重复启动
// 示例
// 栈:A → B → C(C 在栈顶)
// 启动 C:复用 C 实例
// 启动 B:创建新的 B 实例
3. singleTask(栈内复用)
<activity
android:name=".MainActivity"
android:launchMode="singleTask" />
特点:
- 如果 Activity 在栈中,复用该实例,并清除其上所有 Activity
- 如果不在栈中,创建新实例
- 适合主界面
// 示例
// 栈:A → B → C
// 启动 B:复用 B,清除 C,栈变为 A → B
4. singleInstance(单例模式)
<activity
android:name=".MainActivity"
android:launchMode="singleInstance" />
特点:
- 单独一个任务栈
- 全局唯一实例
- 适合独立功能(如拨号界面)
// 示例
// 栈1:A → B
// 栈2:C(singleInstance)
// 启动 C:复用栈2中的 C
Intent Flag
// 使用 Intent Flag 控制启动模式
Intent intent = new Intent(this, MainActivity.class);
// FLAG_ACTIVITY_NEW_TASK:在新任务栈中启动
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// FLAG_ACTIVITY_SINGLE_TOP:等同于 singleTop
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
// FLAG_ACTIVITY_CLEAR_TOP:清除栈顶 Activity
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// FLAG_ACTIVITY_CLEAR_TASK:清除整个任务栈
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
Activity任务栈
任务栈概念
// 任务栈(Task Stack)
// 后进先出(LIFO)的栈结构
// 示例栈结构
// 栈底 ← → 栈顶
// A → B → C → D
// 按 Back 键
// D 出栈 → C 出栈 → B 出栈 → A 出栈
任务栈管理
// 查看任务栈信息
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(10);
for (ActivityManager.RunningTaskInfo task : tasks) {
Log.d("Task", "Task ID: " + task.id);
Log.d("Task", "Top Activity: " + task.topActivity.getClassName());
}
任务栈场景
1. 标准任务栈
// 启动顺序:A → B → C
// 栈结构:A → B → C
// 按 Back:C → B → A
2. singleTask 任务栈
// 启动顺序:A → B → C → B
// 栈结构:A → B(C 被清除)
// 按 Back:B → A
3. singleInstance 任务栈
// 栈1:A → B
// 栈2:C(singleInstance)
// 两个独立的任务栈
Activity与Fragment通信
方式1:接口回调
// Fragment 定义接口
public class MyFragment extends Fragment {
public interface OnFragmentInteractionListener {
void onFragmentAction(String data);
}
private OnFragmentInteractionListener listener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
listener = (OnFragmentInteractionListener) context;
}
}
private void sendDataToActivity() {
if (listener != null) {
listener.onFragmentAction("Data from Fragment");
}
}
}
// Activity 实现接口
public class MainActivity extends AppCompatActivity
implements MyFragment.OnFragmentInteractionListener {
@Override
public void onFragmentAction(String data) {
// 处理 Fragment 传递的数据
Log.d("Activity", "Received: " + data);
}
}
方式2:ViewModel 共享
// ViewModel
public class SharedViewModel extends ViewModel {
private MutableLiveData<String> data = new MutableLiveData<>();
public LiveData<String> getData() {
return data;
}
public void setData(String value) {
data.setValue(value);
}
}
// Activity
public class MainActivity extends AppCompatActivity {
private SharedViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = ViewModelProviders.of(this).get(SharedViewModel.class);
}
}
// Fragment
public class MyFragment extends Fragment {
private SharedViewModel viewModel;
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
viewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
viewModel.getData().observe(this, data -> {
// 观察数据变化
});
}
}
方式3:EventBus
// Fragment 发送事件
EventBus.getDefault().post(new MessageEvent("Data from Fragment"));
// Activity 接收事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
// 处理事件
}
Activity重建
配置变更
// 屏幕旋转等配置变更会导致 Activity 重建
// 默认行为:销毁并重建 Activity
// 保存状态
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("key", value);
}
// 恢复状态
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
String value = savedInstanceState.getString("key");
}
}
避免重建
<!-- AndroidManifest.xml -->
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden" />
// 手动处理配置变更
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// 手动处理配置变更
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// 横屏处理
} else {
// 竖屏处理
}
}
ViewModel 保持数据
// ViewModel 在配置变更时不会重建
public class MyViewModel extends ViewModel {
private MutableLiveData<String> data = new MutableLiveData<>();
public LiveData<String> getData() {
return data;
}
}
// Activity
public class MainActivity extends AppCompatActivity {
private MyViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ViewModel 在配置变更时保持
viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
}
}
Activity转场动画
系统动画
// 启动 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);
共享元素动画
// Activity A
Intent intent = new Intent(this, ActivityB.class);
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(
this,
imageView, // 共享元素
"shared_image" // 共享元素名称
);
startActivity(intent, options.toBundle());
// Activity B
<ImageView
android:transitionName="shared_image" />
自定义动画
<!-- res/anim/slide_in_right.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="100%p"
android:toXDelta="0"
android:duration="300" />
</set>
Activity最佳实践
1. 避免内存泄漏
// ❌ 错误:静态变量持有 Activity
private static Activity sActivity;
// ✅ 正确:使用 Application Context
private static Context sContext = getApplicationContext();
2. 合理使用启动模式
// 主界面使用 singleTask
// 防止重复创建
// 详情页使用 standard
// 可以多个实例
3. 使用 ViewModel
// 使用 ViewModel 保存数据
// 避免在 onSaveInstanceState 中保存大量数据
4. 及时释放资源
@Override
protected void onDestroy() {
super.onDestroy();
// 释放资源
if (handler != null) {
handler.removeCallbacksAndMessages(null);
}
}
面试常见问题
Q1: Activity 生命周期?
答案: onCreate → onStart → onResume → onPause → onStop → onDestroy onRestart(从 onStop 恢复时调用)
Q2: Activity 启动模式?
答案:
- standard:每次创建新实例
- singleTop:栈顶复用
- singleTask:栈内复用
- singleInstance:单例模式
Q3: singleTask 和 singleInstance 的区别?
答案:
- singleTask:在同一个任务栈中复用
- singleInstance:单独一个任务栈,全局唯一
Q4: Activity 重建时如何保存数据?
答案:
- onSaveInstanceState:保存临时数据
- ViewModel:保存 UI 相关数据
- 持久化存储:保存重要数据
Q5: Activity 和 Fragment 如何通信?
答案:
- 接口回调:Fragment 定义接口,Activity 实现
- ViewModel:共享数据
- EventBus:事件总线
最后更新:2024年