天天看点

Eventbus 粘性事件 滞后传递数据。activity间传大数据

项目中遇到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 异常的原因,以及如何解决它,最后再简单总结一下。

  1. Intent 无法传递大数据是因为其内部使用了 Binder 通信机制,Binder 事务缓冲区限制了传递数据的大小。
  2. Binder 事务缓冲区的大小限定在 1MB,但是这个尺寸是共享的,也就是并不是传递 1MB 以下的数据就绝对安全,要视当前的环境而定。
  3. 不要挑战 Intent 传递数据大小的极限,对于大数据,例如长字符串、Bitmap 等,不要考虑 Intent 传递数据的方案。
  4. 解决大数据传递问题,可以从数据源出发,根据数据的标识,还原数据,或者先持久化再还原。也可以使用 EventBus 的粘性事件来解决。