Handler
为什么要使用Handler?因为如果将耗时操作放在主线程中会导致ANR,这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,但是当子线程中有涉及到操作UI的操作时,就会对主线程产生危险,也就是说,更新UI只能在主线程中更新,在子线程中操作是危险的.
这个时候,Handler就出现了来解决这个复杂的问题,由于Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传递)Message对象,(里面包含数据), 把这些消息放入主线程队列中,配合主线程进行更新UI。
对于发送消息的handler和处理消息的handler需要进行传递进行关联,需要在View层例如Activity或者Fragment里需要定义handler并通过handleMessage()方法对传递的msg进行处理;对于实际发送消息的VM层或者P层的类需要又View层将handler传递过去才能进行处理并在handler中处理,这样就是的View层和VM层存在耦合;
EventBus
EventBus是一个Android端优化的publish/subscribe消息总线,简化了应用程序内各组件间、组件与后台线程间的通信。比如请求网络,等网络返回时通过Handler或Broadcast通知UI.
作为一个消息总线,有三个主要的元素:
- Event:事件
- Subscriber:事件订阅者,接收特定的事件;有onEvent,onEventMainThread,onEventBackgroundThread,onEventAsync这四个方法,分别对应不同的处理模式;
- Publisher:事件发布者,用于通知Subscriber有事件发生
事件处理有4种模式:
- PostThread:事件的处理在和事件的发送在相同的进程,所以事件处理时间不应太长,不然影响事件的发送线程,而这个线程可能是UI线程。对应的函数名是onEvent。
- MainThread: 事件的处理会在UI线程中执行。事件处理时间不能太长,这个不用说的,长了会ANR的,对应的函数名是onEventMainThread。
- BackgroundThread:事件的处理会在一个后台线程中执行,对应的函数名是onEventBackgroundThread,虽然名字是BackgroundThread,事件处理是在后台线程,但事件处理时间还是不应该太长,因为如果发送事件的线程是后台线程,会直接执行事件,如果当前线程是UI线程,事件会被加到一个队列中,由一个线程依次处理这些事件,如果某个事件处理时间太长,会阻塞后面的事件的派发或处理。
- Async:事件处理会在单独的线程中执行,主要用于在后台线程中执行耗时操作,每个事件会开启一个线程(有线程池),但最好限制线程的数目。适合于长时间的后台网络请求。
使用步骤:
- 定义事件类型:
public class MyEvent {}
- 定义事件处理方法:
通过注解的方式实现处理方法定义,具体处理方法名不限定
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread
- 注册订阅者:
一般是在event的处理类中会进行eventbus的注册,例如Activity或者Fragment中进行注册
EventBus.getDefault().register(this)
- 发送事件:
在VM或者P层处理完耗时操作后post event,让event订阅者去处理
EventBus.getDefault().post(new MyEvent())
- 取消注册:
在activity的onDestroy()方法中要取消注册,如果一直不释放会导致Bus中的Event队列内存泄露
eventBus.unregister(this);
Handler与EventBus区别
EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。
通过demo分别写了Handler和Eventbus对线程消息传递的处理,大家可以简单对比下两者的区别,可以发现EventBus进行了完全的解耦。
本文中和demo中使用的是greenrobot的EventBus,github地址如下:
https://github.com/greenrobot/EventBus