项目中遇到activity传大数据集合。使用EventBus滞后传统的功能。网上找到的阿里开发手册的内容 。记录笔记。
阿里给出的方案,是通过 EventBus 来传递数据。
EventBus 的 粘性事件
很多商业项目其实都用到了 EventBus,这里就简单介绍如何使用 EventBus 的粘性事件来完成数据在 Activity 间的传递。
EventBus 是一个 Android 端优化的 Publish/subscribe 消息总线,简化了应用程序内各个组件间、组件与后台线程间的通信。
在 Activity 中使用 EventBus,需要根据 Activity 的生命周期,成对调用 register() 和 unregister() 方法。普通的事件,只会发生在 register() 之后,在注册前发生的事件,统统都收不到。
这里利用的 EventBus 的粘性事件(Sticky Event)来实现,EventBus 内部维护了一个 Map 对象 stickyEvents,用于缓存粘性事件。
粘性事件使用 postSticky() 方法发送,它会将事件缓存到 stickyEvents 这个 Map 对象中,以待下次注册时,将这个事件取出,抛给注册的组件。以此来达到一个粘性的滞后事件发送和接收。
接下来我们看看 EventBus 粘性事件的使用细节。
1. 注解的区别
粘性事件的注解和普通事件的注解略有区别,需要添加 threadMode 和 sticky 参数。
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
publicvoidonStickyEvent(MyStickyEvent event){
//...
}
注意,这两个额外的参数是必须的。
2. 调用方法的区别
在发送消息的时候,需要使用 postSticky() 来替换掉 post() 方法。
需要注意的是,粘性事件是使用 Map 结构缓存的,并且是使用事件对象类型当 Key 进行缓存,所以对于同类型的数据,它只会缓存最后发送的数据。
3. 注意清理事件
前面也提到,粘性事件是存储在一个 Map 对象中的,它是不会主动清理其中存储的对象的,需要开发者手动清理。
EventBus 提供了两类方法 removeStickyEvent() 和 removeAllStickyEvents() 方法,分别用来清理固定数据以及全部数据。
我们需要在合适的时机,手动的调用这两类方法,清理粘性事件。如果不对粘性事件进行清理,每次 register() 的时候,都会收到粘性事件。
4. EventBus 粘性事件的问题
粘性事件本身是脱离了 Android Intent 数据传递的这一套机制的,要知道 Activity 会在一些特殊情况下被销毁重建,在此情况下,通过 Intent 传递的数据,是可以继续从 Intent 中获取恢复到上一次页面传递的数据。
而通过 EventBus 的粘性事件,则可能在销毁重建时,造成数据丢失。
如果想要使用 EventBus 的粘性事件,来在页面间传递大数据,还是有不少细节,需要根据业务来调整的。
四、小结时刻
今天我们聊到了在 Activity 间,通过 Intent 传递大数据会触发 TransactionTooLargeException 异常的原因,以及如何解决它,最后再简单总结一下。
- Intent 无法传递大数据是因为其内部使用了 Binder 通信机制,Binder 事务缓冲区限制了传递数据的大小。
- Binder 事务缓冲区的大小限定在 1MB,但是这个尺寸是共享的,也就是并不是传递 1MB 以下的数据就绝对安全,要视当前的环境而定。
- 不要挑战 Intent 传递数据大小的极限,对于大数据,例如长字符串、Bitmap 等,不要考虑 Intent 传递数据的方案。
- 解决大数据传递问题,可以从数据源出发,根据数据的标识,还原数据,或者先持久化再还原。也可以使用 EventBus 的粘性事件来解决。