Bundle中putParcelable和putBinder

在 Android 中,Bundle 类提供了一种灵活的方法来存储和传递各种类型的数据。putParcelableputBinderBundle 类中常用的方法,用于存储和传递不同类型的数据对象。

putParcelable

putParcelable 方法用于将实现了 Parcelable 接口的对象存储到 Bundle 中。Parcelable 接口是 Android 中的一种序列化机制,专为高效传输对象数据设计的。

使用示例:

假设有一个自定义类 MyParcelable 实现了 Parcelable 接口:

public class MyParcelable implements Parcelable {
   
   
    private int mData;

    public MyParcelable(int data) {
   
   
        mData = data;
    }

    protected MyParcelable(Parcel in) {
   
   
        mData = in.readInt();
    }

    public static final Creator<MyParcelable> CREATOR = new Creator<MyParcelable>() {
   
   
        @Override
        public MyParcelable createFromParcel(Parcel in) {
   
   
            return new MyParcelable(in);
        }

        @Override
<think>我们分析用户提供的代码片段: ```java public static Bundle createBundle(List<KzLightBean> lightBeans) { Bundle bundle = new Bundle(); bundle.putParcelable(KEY_BEAN, (Parcelable) lightBeans); return bundle; } ``` 这段代码的目的是将一个`List<KzLightBean>`对象放入Bundle中。但是,这里存在几个关键问题: ### 一、主要问题分析 #### 1. **类型不匹配错误** - `Bundle.putParcelable(String, Parcelable)`方法要求第二个参数必须是一个实现了`Parcelable`接口的对象。 - 然而,`List<KzLightBean>`本身并没有实现`Parcelable`接口,即使`KzLightBean`实现了`Parcelable`,`List`接口也不是`Parcelable`。 - 因此,将`List`强制转换为`Parcelable`会导致运行时错误(`ClassCastException`)。 #### 2. **正确的集合传递方式** - Android提供了专门的方法来传递集合: - 对于`ArrayList`(注意:必须是`ArrayList`,而不是`List`),可以使用`Bundle.putParcelableArrayList(String, ArrayList<? extends Parcelable>)`方法。 - 如果集合中的元素是`SparseArray`,则使用`Bundle.putSparseParcelableArray`。 - 对于其他类型的集合,需要先转换为`ArrayList`(如果元素是`Parcelable`)或者使用`Serializable`。 #### 3. **`KzLightBean`的要求** - 使用`putParcelableArrayList`的前提是`KzLightBean`必须实现了`Parcelable`接口。否则,即使使用`ArrayList`也会出错。 ### 二、修正后的代码 根据上述分析,修正代码需要两个步骤: 1. **确保`KzLightBean`实现`Parcelable`接口**(假设已经实现,如果没有,需要先实现) 2. **修改Bundle的写入方式**: ```java public static Bundle createBundle(List<KzLightBean> lightBeans) { Bundle bundle = new Bundle(); // 将List转换为ArrayList(如果已经是ArrayList则无需转换,但为了安全可以转换) ArrayList<KzLightBean> arrayList = new ArrayList<>(lightBeans); bundle.putParcelableArrayList(KEY_BEAN, arrayList); return bundle; } ``` ### 三、替代方案:使用`Serializable` 如果`KzLightBean`没有实现`Parcelable`,而是实现了`Serializable`,那么可以这样写: ```java public static Bundle createBundle(List<KzLightBean> lightBeans) { Bundle bundle = new Bundle(); // 要求KzLightBean实现Serializable接口 bundle.putSerializable(KEY_BEAN, (Serializable) lightBeans); return bundle; } ``` > 注意:`Parcelable`是Android推荐的序列化方式,效率比`Serializable`高[^1]。 ### 四、数据大小限制与异常处理 - **TransactionTooLargeException风险**:当传递的数据量过大(超过1MB)时,可能会抛出此异常。解决方案: - 避免在Bundle中放置过多数据 - 使用全局数据存储(如ViewModel、数据库、文件)传递数据标识符 ```java // 使用ViewModel共享大数据 public class SharedViewModel extends ViewModel { private final MutableLiveData<List<KzLightBean>> data = new MutableLiveData<>(); public void setData(List<KzLightBean> newData) { data.setValue(newData); } public LiveData<List<KzLightBean>> getData() { return data; } } // 在Activity中设置数据 viewModel.setData(lightBeans); // 在Fragment中获取数据 viewModel.getData().observe(this, beans -> { // 更新UI }); ``` ### 五、最佳实践总结 | 场景 | 推荐方法 | 注意事项 | |------|----------|----------| | 小数据量(<100KB) | `putParcelableArrayList` | 要求元素实现`Parcelable` | | 大数据量 | ViewModel + LiveData | 避免使用Bundle传递 | | 跨进程传递 | Messenger/Binder | 需显式处理进程间通信 | | 持久化存储 | 数据库/文件 | Bundle不适合持久化 | ### 六、相关问题 1. 如何实现`Parcelable`接口?有哪些注意事项? 2. 在Fragment之间传递数据有哪些安全的方式? 3. 如何处理Android中的`TransactionTooLargeException`? 4. `Parcelable``Serializable`在性能上有何差异? 5. 使用ViewModel传递数据有什么优势限制? > 参考资料: > [Android Bundle文档](https://developer.android.com/reference/android/os/Bundle) > [Parcelable实现指南](https://developer.android.com/reference/android/os/Parcelable)[^1] > [处理大型数据](https://developer.android.com/guide/components/activities/parcelable-and-bundle#kotlin) </think> ### Bundle传递List\<KzLightBean\>代码分析与优化 #### 一、原始代码问题分析 ```java public static Bundle createBundle(List<KzLightBean> lightBeans) { Bundle bundle = new Bundle(); bundle.putParcelable(KEY_BEAN, (Parcelable) lightBeans); return bundle; } ``` 主要存在两个关键问题: 1. **类型转换错误** `List<KzLightBean>` 不能直接转换为 `Parcelable`。即使 `KzLightBean` 实现了 `Parcelable` 接口,Java集合本身并未实现该接口,会导致运行时抛出 `ClassCastException`。 2. **正确的集合传递方式** Android提供了专门的API传递集合: ```java // 需要转换为 ArrayList bundle.putParcelableArrayList(KEY_BEAN, new ArrayList<>(lightBeans)); ``` #### 二、修正方案 ```java public static Bundle createBundle(List<KzLightBean> lightBeans) { Bundle bundle = new Bundle(); // 方案1:使用putParcelableArrayList(推荐) if (lightBeans instanceof ArrayList) { bundle.putParcelableArrayList(KEY_BEAN, (ArrayList<KzLightBean>) lightBeans); } else { bundle.putParcelableArrayList(KEY_BEAN, new ArrayList<>(lightBeans)); } // 方案2:使用putSerializable(备选) // bundle.putSerializable(KEY_BEAN, new ArrayList<>(lightBeans)); return bundle; } ``` ##### 注意事项: 1. **KzLightBean必须实现Parcelable** ```java public class KzLightBean implements Parcelable { // 实现Parcelable要求的方法 @Override public void writeToParcel(Parcel dest, int flags) { /*...*/ } public static final Creator<KzLightBean> CREATOR = new Creator<>() { /*...*/ }; } ``` 2. **数据量较大时的处理** 当列表数据量过大时,使用Bundle传递可能导致 `TransactionTooLargeException`: ```java // 解决方案:通过ViewModel共享数据 public class SharedViewModel extends ViewModel { private final MutableLiveData<List<KzLightBean>> data = new MutableLiveData<>(); public void setData(List<KzLightBean> list) { data.setValue(list); } public LiveData<List<KzLightBean>> getData() { return data; } } ``` #### 三、数据接收端处理 ```java // 在Fragment/Activity中获取数据 List<KzLightBean> beans = getArguments() .getParcelableArrayList(KEY_BEAN); ``` #### 四、性能对比 | 传递方式 | 优点 | 缺点 | |-------------------------|-----------------------|---------------------------| | `putParcelableArrayList`| 高效,Native层实现 | 需实现Parcelable | | `putSerializable` | 无需额外接口实现 | 性能低(反射操作) | | ViewModel共享 | 无大小限制 | 限定同进程 | > Parcelable序列化速度比Serializable快10倍以上 #### 五、最佳实践建议 1. **小数据量**(<1MB) 使用`putParcelableArrayList`+类型检查 2. **大数据量** ```java // 使用全局单例或ViewModel DataRepository.getInstance().setLightBeans(lightBeans); ``` 3. **跨进程通信** 使用AIDL接口定义传输协议: ```java interface ILightService { void sendLightBeans(in List<KzLightBean> beans); } ``` --- ### 相关问题 1. 如何正确实现Parcelable接口避免`BadParcelableException`? 2. 使用ViewModel共享数据需要注意哪些生命周期问题? 3. 如何优化大型列表的序列化/反序列化性能? 4. 跨进程传递复杂数据结构有哪些替代方案? 5. 如何检测并避免`TransactionTooLargeException`? > 参考:[Android Parcelable官方文档](https://developer.android.com/reference/android/os/Parcelable)[^1] > [Bundle数据传输限制](https://developer.android.com/reference/android/os/TransactionTooLargeException)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彬_小彬

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值