Android随笔-Bundle与Binder

Bundle 是什么

Bundle 是 Android 中用于存储键值对数据 的容器类,本质上是一个 Map 结构,专门用于在不同组件之间传递轻量级数据。

常见使用场景(Activity ↔ Fragment 通信)

java 复制代码
// Activity 向 Fragment 传递数据
Bundle bundle = new Bundle();
bundle.putString("user_name", "张三");
bundle.putInt("user_age", 20);

MyFragment fragment = new MyFragment();
fragment.setArguments(bundle);  // 设置参数

// Fragment 中接收数据
Bundle args = getArguments();
String name = args.getString("user_name");

Bundle 能传递的数据类型

  • 基本类型:String、int、boolean、float、long、double
  • 数组和集合:String\[\]、ArrayList、ArrayList 等
  • 实现了 Parcelable 或 Serializable 接口的对象

Binder 是什么

Binder 是 Android 中**跨进程通信(IPC)**的核心机制,是 Linux 内核中的一个驱动程序,也是 Android 系统底层最重要的 IPC 方式。

核心特点

  • 底层机制:基于 Linux 内核的 Binder 驱动
  • 跨进程:用于不同进程之间的通信
  • C/S 架构:通过 IBinder 接口,客户端调用服务端暴露的方法
  • 安全性:Android 为每个应用分配独立的 UID,Binder 内核驱动进行权限校验

典型使用场景

  • ActivityManagerService(AMS)与 App 进程通信
  • startService() / bindService() 与 Service 通信
  • AIDL(Android Interface Definition Language)定义跨进程接口

Bundle 与 Binder 的区别

维度 Bundle Binder
层级 应用层 API 系统底层机制(内核驱动)
作用 数据容器,传递数据 跨进程通信的"桥梁"
进程范围 同进程内传递 主要用于跨进程通信
数据大小 较小(官方建议 < 1MB,实际几百 KB 就可能触发 TransactionTooLargeException 理论上无严格限制(但受 Binder 缓冲区 1MB 限制)
实现原理 内部使用 ArrayMap 存储键值对 基于 Linux 内核的内存映射(mmap)
使用复杂度 简单,直接 put/get 复杂,需要定义 AIDL 接口、实现 Stub 等
性能 同进程内高效 跨进程有额外序列化/反序列化开销

Bundle 与 Binder 的联系

虽然两者定位和层级完全不同,但在实际开发中紧密配合

1. Bundle 底层依赖 Binder

当你调用 startActivity(intent) 时:

Intent 携带 Bundle → AMS(Binder 跨进程调用)→ 目标 Activity

这里的 Bundle 数据通过 Binder 机制跨进程传递到系统服务,再由系统服务分发到目标进程。

2. 数据序列化方式相通

Bundle 中传递自定义对象时,需要实现 Parcelable 接口。而 Parcelable 的 writeToParcel() 和 createFromParcel() 方法,底层正是通过 Parcel 进行序列化------Parcel 是 Binder 通信的数据载体

java 复制代码
// Parcelable 的 writeToParcel 方法
public void writeToParcel(Parcel out, int flags) {
    out.writeString(name);      // 写入 Parcel(Binder 的数据包)
    out.writeInt(age);
}

3. 共同受 Binder 事务限制

Bundle 传递数据过大时会抛出 TransactionTooLargeException,根本原因是:Bundle 的数据最终要通过 Binder 驱动传输,而 Binder 内核缓冲区只有 1MB(且被所有并发事务共享)。

总结

Bundle 是"装数据的盒子",Binder 是"送盒子的快递系统"。 Bundle 负责打包数据,Binder 负责在进程间运送这个盒子。当 Activity 与 Fragment 在同进程内通信时,Bundle 直接传递;当涉及跨进程(如启动另一个 App 的 Activity)时,Bundle 的数据就需要 Binder 来运输。

延伸

Activity 与 Fragment 通信的其他方式

方式 适用场景 说明
setArguments(Bundle) 初始化传参 官方推荐,Fragment 重建时参数不会丢失
接口回调 Fragment → Activity 通信 Fragment 定义接口,Activity 实现
ViewModel + LiveData 共享数据 现代推荐方案,生命周期感知,自动处理配置变更
直接调用 不推荐 耦合度高,Fragment 不应直接持有 Activity 引用