Files
mkdocs/docs/android面试/核心组件/Activity详解.md
2026-01-15 11:53:37 +08:00

12 KiB
Raw Blame History

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 → CC 在栈顶)
// 启动 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" />

特点:

  • 单独一个任务栈
  • 全局唯一实例
  • 适合独立功能(如拨号界面)
// 示例
// 栈1A → B
// 栈2CsingleInstance
// 启动 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
// 按 BackC → B → A

2. singleTask 任务栈

// 启动顺序A → B → C → B
// 栈结构A → BC 被清除)
// 按 BackB → A

3. singleInstance 任务栈

// 栈1A → B
// 栈2CsingleInstance
// 两个独立的任务栈

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);
    }
}

方式2ViewModel 共享

// 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 -> {
            // 观察数据变化
        });
    }
}

方式3EventBus

// 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 启动模式?

答案:

  1. standard:每次创建新实例
  2. singleTop:栈顶复用
  3. singleTask:栈内复用
  4. singleInstance:单例模式

Q3: singleTask 和 singleInstance 的区别?

答案:

  • singleTask:在同一个任务栈中复用
  • singleInstance:单独一个任务栈,全局唯一

Q4: Activity 重建时如何保存数据?

答案:

  1. onSaveInstanceState:保存临时数据
  2. ViewModel:保存 UI 相关数据
  3. 持久化存储:保存重要数据

Q5: Activity 和 Fragment 如何通信?

答案:

  1. 接口回调Fragment 定义接口Activity 实现
  2. ViewModel:共享数据
  3. EventBus:事件总线

最后更新2024年