Skip to content

Bundle

一、Bundle 的定义与本质

Bundle 是 Android 系统中用于存储 键值对(Key-Value) 数据的数据容器类,其核心特性包括:

  • 跨进程序列化:实现 Parcelable 接口,支持高效序列化与反序列化
  • 数据类型支持:可存储基本类型、StringParcelable 对象、Serializable 对象及它们的集合类型
  • 轻量化设计:基于 ArrayMap 实现(相比 HashMap 内存占用更低)

经典使用场景

java
// 状态保存  
@Override  
protected void onSaveInstanceState(Bundle outState) {  
    outState.putString("key_text", "Hello Bundle");  
}  

// 状态恢复  
@Override  
protected void onCreate(Bundle savedInstanceState) {  
    if (savedInstanceState != null) {  
        String text = savedInstanceState.getString("key_text");  
    }  
}

二、Bundle 的常见使用场景

1. Activity/Fragment 状态保存与恢复

  • 触发时机
    • 屏幕旋转等配置变更
    • 系统内存不足回收后台 Activity
    • 用户按下 Home 键/切换应用
  • 生命周期关联
    onSaveInstanceState()onRestoreInstanceState() / onCreate()

2. Activity/Fragment 间数据传输

kotlin
// 发送方  
val intent = Intent(this, TargetActivity::class.java).apply {  
    putExtra("user", User("Alice", 25))  
}  
startActivity(intent)  

// 接收方  
val user = intent?.getParcelableExtra<User>("user")

3. 进程间通信(IPC)

  • 通过 Binder 驱动传递 Bundle 数据(如 ServiceActivity 通信)
  • 跨进程数据需实现 Parcelable 接口

4. Fragment 参数传递

kotlin
val fragment = MyFragment().apply {  
    arguments = bundleOf("id" to 1001)  
}

三、Bundle 的核心 API 方法

数据存取方法

方法签名说明
putString(String key, String value)存储字符串
getString(String key)读取字符串
putParcelable(String key, Parcelable value)存储可序列化对象
getParcelable(String key)读取可序列化对象
putBundle(String key, Bundle value)嵌套存储 Bundle(树形结构)

辅助方法

方法签名说明
containsKey(String key)检查是否包含指定键
remove(String key)移除指定键值对
keySet()获取所有键的集合
size()获取键值对数量

四、Bundle 的底层实现机制

1. 数据结构设计

  • 底层使用 双数组存储ArrayMap 结构):
    • mKeys: 存储键名的 Object[] 数组
    • mValues: 存储值的 Object[] 数组
  • 优势:内存紧凑,适合少量数据场景

2. 序列化与反序列化

  • 基于 Parcel 实现高效二进制序列化:
java
  // 序列化过程  
  Parcel parcel = Parcel.obtain();  
  bundle.writeToParcel(parcel, 0);  
  byte[] bytes = parcel.marshall();  

  // 反序列化  
  Parcel newParcel = Parcel.obtain();  
  newParcel.unmarshall(bytes, 0, bytes.length);  
  Bundle newBundle = new Bundle();  
  newBundle.readFromParcel(newParcel);

3. 数据大小限制

  • TransactionTooLargeException
    • Android 限制单个 Binder 事务数据不超过 1MB
    • 包含 Bundle 的 IPC 调用需控制数据量

4. 版本兼容性

  • Android 7.0+:Bundle 数据存储改用 PersistableBundle 优化
  • Android 10+:严格模式检测 Bundle 内存泄漏

五、最佳实践与常见问题

1. 状态保存原则

  • 轻量化存储:仅保存 UI 状态(如输入文本、滚动位置),避免存储大对象
  • ViewModel 优先:复杂数据应通过 ViewModel + LiveData 管理

2. 避免直接存储 Bitmap

kotlin
// 错误做法(易触发 TransactionTooLargeException)  
outState.putParcelable("bitmap", largeBitmap)  

// 正确做法:存储 URI 或文件路径  
outState.putString("image_path", "/sdcard/image.jpg")

3. 版本间差异处理

  • 使用 @RequiresApi 注解处理不同 API 级别的方法兼容性
  • 使用 Build.VERSION.SDK_INT 做运行时版本判断

4. 调试技巧

  • 查看 Bundle 内容
    shell
    adb shell dumpsys activity activities | grep "Hist #"
  • 检测内存泄漏:通过 Android Studio 的 Memory Profiler 分析 Bundle 内存占用

上次更新于: