Android四大组件之Activity解析

95 阅读10分钟

核心定位与设计哲学:

  1. 用户交互的容器与入口:

    • 根本目的:Activity 是 Android 应用呈现用户界面(UI)和处理用户交互的核心单元。它是用户与应用进行接触的“窗口”或“屏幕”。
    • 任务(Task) 的构建块:多个 Activity(通常来自同一应用,但也可能来自不同应用)通过特定的启动模式 (launchMode) 和 Intent 标志 (Intent Flags) 组织成一个逻辑上的用户任务(如“查看邮件列表 -> 阅读邮件 -> 回复邮件”)。Activity 的启动、入栈、出栈管理由系统(主要是 ActivityManagerService - AMS)负责。
  2. 生命周期的强制性管理:

    • 系统驱动: Activity 的生命周期(onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy(), onRestart())并非由开发者直接控制,而是由系统根据用户操作、设备状态(如旋转、内存压力、来电)、其他组件(如新 Activity 启动) 来严格管理和回调。
    • 状态保存与恢复: onSaveInstanceState(Bundle)onRestoreInstanceState(Bundle) 机制是核心,用于在 Activity 被系统非自愿销毁(如配置变更、内存回收)时保存瞬时 UI 状态(非持久化数据),并在重建时恢复。深度理解: Bundle 大小限制(通常 ~1MB,因设备/版本而异)是关键约束,决定了什么能存、什么不能存。过度依赖它会导致 TransactionTooLargeException。
    • 资源管理: 生命周期回调是正确获取(onStart/onResume)和释放(onPause/onStop/onDestroy)系统资源(传感器、摄像头、数据库连接、网络连接、广播接收器)的关键时机。泄漏常因违反此原则而发生。
  3. 上下文(Context)的化身:

    • ActivityContext 的子类。它提供了访问应用级资源(字符串、图片、布局)、系统服务LayoutInflater, WindowManager, getSystemService())、启动其他组件startActivity(), startService(), sendBroadcast())的能力。
    • 深度理解: Activity 持有的 ContextActivity Context,其生命周期与 Activity 本身绑定。错误地长期持有 Activity Context(如在静态变量、后台线程、单例中)是内存泄漏的最常见根源之一。需要应用级资源时,优先使用 Application Context (getApplicationContext())。

超深度剖析:与系统服务的交互 (AMS & WMS)

  1. ActivityManagerService (AMS):

    • 大脑中枢: AMS 是系统级服务,管理着所有应用进程及其 Activity 的生命周期、任务栈、权限等。
    • 启动流程深度解析:
      • startActivity() -> Instrumentation.execStartActivity() -> 通过 Binder IPC 调用 ActivityTaskManagerService (ATMS, 较新版本中 AMS 的一部分职责) 的 startActivity
      • ATMS 验证权限、解析 Intent、确定目标 Activity、处理启动模式/任务栈。
      • 如果目标应用进程未运行,ATMS 请求 Zygote 进程孵化新进程。
      • ATMS 通过 Binder 调用目标进程的 ApplicationThread (一个实现了 IApplicationThread 接口的 Binder 对象,存在于应用进程中)。
      • ApplicationThread 将启动请求调度到主线程 (ActivityThreadH - Handler),调用 ActivityThread.handleLaunchActivity()
      • handleLaunchActivity() -> performLaunchActivity()创建 Activity 实例 (通过反射调用 ClassLoader.loadClass().newInstance()),创建 Application 实例(如果尚未创建),创建 ContextImpl (真正的 Context 实现),ActivityContextImpl 关联 (activity.attach(Context, ...)),调用 Instrumentation.callActivityOnCreate() -> activity.onCreate()
      • handleLaunchActivity() -> handleResumeActivity() -> performResumeActivity() -> activity.performResume() -> Instrumentation.callActivityOnResume() -> activity.onResume()
    • 生命周期回调: AMS 通过 ApplicationThreadBinder IPC 向应用进程发送 scheduleTransaction 请求(如 PauseActivityItem, ResumeActivityItem),ActivityThreadH (Handler) 处理这些事务,最终调用对应的生命周期方法 (onPause(), onResume() 等)。
    • 任务栈管理: AMS 维护着 ActivityRecord, TaskRecord (或新版本中的概念),处理 Activity 的入栈 (push)、出栈 (pop)、移动到前台/后台。启动模式 (standard, singleTop, singleTask, singleInstance) 和 Intent Flags (FLAG_ACTIVITY_NEW_TASK, FLAG_ACTIVITY_CLEAR_TOP 等) 直接影响 AMS 的栈操作逻辑。
  2. WindowManagerService (WMS):

    • 窗口管家: WMS 管理屏幕上所有窗口的层级、布局、焦点、动画、输入事件分发。
    • ActivityWindow
      • 每个 Activity 都关联一个顶层 Window 对象 (通常是 PhoneWindow)。
      • Activity.attach() 中会创建 PhoneWindow,并设置 WindowManager (WindowManagerImpl)。
      • setContentView(int layoutResId) 的深度流程:
        • getWindow().setContentView(layoutResId) -> PhoneWindow.setContentView()
        • PhoneWindow 创建 DecorView (顶级 ViewGroup),将开发者布局作为子视图添加到 DecorView 的特定位置 (mContentParent)。
        • ActivityThread.handleResumeActivity() 中,在 onResume() 之后,会调用 wm.addView(decorView, ...) -> 通过 Binder IPC 调用 WMS.addWindow()
        • WMS 为窗口分配 Surface(绘图表面),管理其 Z-order,并将其合成到屏幕上。
    • 输入事件分发:
      • 硬件输入事件 -> InputReader -> InputDispatcher -> 通过 InputChannel (通常是 SocketPair) 发送到拥有焦点窗口的应用进程。
      • 应用进程的 ViewRootImpl 通过 InputEventReceiver 接收事件,在 UI 线程中开始 View 树的事件分发流程 (DecorView -> ... -> 目标 View)。
      • ActivitydispatchTouchEvent() 是事件进入应用 View 体系的第一站。

内部机制与高级主题:

  1. ActivityThread

    • 应用的主线程入口核心调度器main() 方法启动消息循环 (Looper/Handler)。
    • 它是与 AMS 通信的桥梁(通过 ApplicationThread Binder 代理)。
    • 负责创建 ActivityService 实例,并调度它们的生命周期回调。
    • H (Handler): 处理来自 AMS 的消息 (LAUNCH_ACTIVITY, RESUME_ACTIVITY, PAUSE_ACTIVITY 等) 和应用内部发送到主线程的消息 (Runnable)。
  2. Instrumentation

    • 监控应用与系统交互的“钩子”。每个应用进程有一个 Instrumentation 实例。
    • 深度作用:Activity 生命周期方法 (onCreate, onStart 等) 被调用前和执行后Instrumentation 会收到通知 (callActivityOnCreate(), callActivityOnStart() 等)。这为 测试框架(如 Espresso, UI Automator)提供了监控和干预的切入点。也用于性能分析工具跟踪生命周期耗时。
  3. ContextImplContextWrapper

    • Activity 继承自 ContextThemeWrapper -> ContextWrapper -> Context
    • ContextWrapper 是代理模式,将大部分方法调用委托给其内部的 mBase 成员(一个 ContextImpl 实例)。
    • ContextImplContext API 的真正实现者。它包含了 Activity 所需的核心数据和功能:ResourcesManager 引用、包信息、Activity 资源目录、ClassLoaderDisplay 信息、Application 引用等。Activity.attach() 方法中创建并关联了这个 ContextImpl
  4. 配置变更 (Configuration Change):

    • 原因: 屏幕旋转、语言切换、字体缩放等。
    • 默认行为: 系统销毁当前 Activity (调用 onSaveInstanceState -> onPause -> onStop -> onDestroy),然后立即用新的配置重建它 (调用 onCreate -> onStart -> onResume,并传入保存的 Bundle)。
    • android:configChanges 在 Manifest 中声明,允许 Activity 自行处理特定配置变更。系统不再重建 Activity,而是调用其 onConfigurationChanged(Configuration newConfig) 方法。深度风险: 滥用此属性(特别是 screenSize/smallestScreenSize)可能导致资源未正确更新(如布局未重新 inflate 以适应新尺寸),引发 UI 错乱。仅在充分理解并手动处理了所有副作用时才使用。
  5. 启动模式 (launchMode) 与任务亲和性 (taskAffinity):

    • 启动模式深度行为:
      • standard:默认。每次都创建新实例。
      • singleTop:目标 Activity 已在栈顶则复用 (onNewIntent()),否则创建新实例。
      • singleTask:在指定亲和性的任务中查找(默认是应用亲和性)。找到则将其前置并清除其上的所有 Activity (触发 onNewIntent()),未找到则创建新实例放入该任务。
      • singleInstance:独占一个任务栈,该栈只容纳它自己。后续启动复用该实例 (onNewIntent())。极其特殊,慎用(如来电接听界面)。
    • Intent Flags: 提供更精细的控制,优先级高于 Manifest 中的 launchMode。如 FLAG_ACTIVITY_NEW_TASK(新任务栈), FLAG_ACTIVITY_CLEAR_TOP(清除目标之上的 Activity), FLAG_ACTIVITY_SINGLE_TOP(同 singleTop)。
    • 任务亲和性 (taskAffinity):定义 Activity 理想归属的任务。默认是应用的包名。singleTaskallowTaskReparenting 属性依赖它。
  6. onNewIntent(Intent)

    • Activity 的实例已经存在(因 singleTop, singleTask, singleInstance 启动模式或 FLAG_ACTIVITY_CLEAR_TOP 标志)并被再次要求启动时,系统不会创建新实例,而是将新的 Intent 传递给现有实例,并调用此方法。
    • 关键点: 必须在此方法中使用新的 Intent 更新数据/UI。注意 getIntent()onNewIntent() 调用后不会自动更新,通常需要调用 setIntent(newIntent)
  7. 结果传递 (startActivityForResult() -> onActivityResult()):

    • 启动者 Activity 通过 startActivityForResult(intent, requestCode) 启动目标 Activity
    • 目标 Activity 结束时调用 setResult(int resultCode, Intent data)
    • 系统销毁目标后,会回调启动者 ActivityonActivityResult(int requestCode, int resultCode, Intent data)
    • 深度演变: 该 API 已被标记为 deprecated (弃用)。Google 推荐使用 Activity Result API (通过 ActivityResultLauncher),它更类型安全、解耦、易于测试,并支持在非 Activity 类(如 Fragment、ViewModel)中处理结果。

性能、优化与疑难杂症:

  1. 冷启动/热启动优化:

    • 冷启动: 应用进程不存在,从头加载。优化点:减少 Application.onCreate()Activity.onCreate() 的耗时(懒加载、异步初始化、避免 I/O)、使用启动屏 (SplashScreen API)、优化布局层次/过度绘制。
    • 热启动: 应用进程在后台,只需将 Activity 带到前台。优化点:快速恢复 UI (onCreate/onRestart 中避免阻塞操作)、利用 onSaveInstanceState 高效恢复状态。
  2. 内存泄漏:

    • 主要根源: 长期持有 Activity Context 引用。
    • 常见场景: 静态变量引用、匿名内部类 (隐式持有外部类 Activity 实例)、Handler (延迟消息持有 Handler 引用 -> Handler 持有 Activity 引用)、未反注册的监听器 (广播、传感器、EventBus)、单例不当持有、后台线程持有。
    • 检测: LeakCanary, Android Studio Profiler。
    • 预防: 使用 Application Context、WeakReference、及时反注册、避免非静态内部类、注意 Handler/Runnable 的生命周期、ViewModel 处理 UI 相关数据。
  3. ANR (Application Not Responding):

    • Activity 相关的原因: 主线程阻塞。生命周期方法 (onCreate, onStart, onResume, onPause) 或 onKeyDown()onTouchEvent() 等输入事件处理方法中执行耗时操作(网络请求、大文件读写、复杂计算)。
    • 规避: 严格禁止在 UI 线程执行耗时操作。使用 AsyncTask (已弃用但理解其原理)、Thread/HandlerExecutorServiceKotlin CoroutinesRxJava 等异步机制。将耗时操作移至后台线程,完成后通过 Handler、LiveData、Flow 等方式安全更新 UI。
  4. 大图/大数据传递:

    • 避免通过 Intent 的 Bundle 传递大对象(Bitmap、大集合): 容易触发 TransactionTooLargeExceptionBundle 传输涉及 Binder 事务缓冲区限制。
    • 替代方案: 使用持久化存储(数据库、文件、SharedPreferences - 注意大小和类型)、内存缓存(单例、ViewModel)、IPC 机制(如 Messenger、AIDL,但仍有大小限制)、ContentProvider
  5. FragmentActivity 的关系:

    • Fragment 必须嵌入在 Activity (或其 FragmentContainer) 中。ActivityFragment 的宿主。
    • FragmentManagerActivity 管理。
    • Activity 提供 Fragment 所需的生命周期和 Context
    • 复杂的 UI 通常由多个 Fragment 组合在一个 Activity 中实现,Activity 充当协调者。单 Activity 架构 (如 Navigation Component) 充分利用了这一点。

总结与演进:

  • Activity 是 Android UI 和交互的基石,理解其深度原理(生命周期管理、AMS/WMS 交互、启动模式、Context 机制)对构建健壮、高效、符合平台规范的应用至关重要。
  • Google 在持续改进和简化基于 Activity 的开发:
    • Activity Result API 替代 startActivityForResult/onActivityResult
    • SavedStateHandle (在 ViewModel 中) 提供更现代、可测试的状态恢复机制,部分替代 onSaveInstanceState Bundle。
    • Lifecycle 将生命周期状态抽象成可观察对象 (LifecycleOwner),允许任何组件(如 ViewModel, Presenter)感知 Activity/Fragment 生命周期,避免在它们内部写大量生命周期回调代码。
    • Compose 的兴起: Jetpack Compose 声明式 UI 框架改变了对 Activity 内部 UI 构建的传统认知 (setContentView + XML/View),但 Activity 作为 UI 容器和生命周期管理者的核心角色依然不变。ComponentActivity 提供了与 Compose 的良好集成。

超深度分析的核心在于认识到 Activity 不仅仅是一个类或 API 集合,它是 Android 系统管理应用 UI 和任务的一个关键抽象,其行为受到系统服务(AMS, WMS)的严格管控,并与进程模型、Binder IPC、窗口系统、资源管理等底层机制深度交织。 透彻理解这些层面的交互,是解决复杂问题、进行高级优化和架构设计的基础。