前言
以前每个页面与每个页面业务逻辑传递让你不知所措,一个又一个接口回调,让你晕头转向,一个又一个参数让你混乱不堪。EventBus一个耦合度低的让你害怕的框架。
什么是EventBus
EventBus是一个消息总线,以观察者模式实现,用于简化程序的组件,可以轻易切换线程,实现各组件之间的刷新通知,以及参数的传递。EventBus3.0跟之前版本的区别
是介入了annotation @Subscribe,取代了以前约定命名的方式。
EventBus的优点
它代替了广播,startActivityforResult,Handle,异步回调等,来实现各个组件间,线程间的通讯,优点是开销小,代码更优雅,以及将发送者与接受者解耦。
EventBus封装
我们今天直接看EventBus封装过程。
EventBus的订阅,接收,发送,我们都放在基类BaseActivity/BaseFragment中完成(EventBus.getDefault().register(this)
订阅事件,发起通信的逻辑直接调用EventBus.getDefault().post(Object event)
来发布事件)。
EventBus封装实战
在Gradle中添加EventBus
依赖:
compile ‘org.greenrobot:eventbus:3.0.0‘
封装一下EventBus
的订阅、取消订阅、发布等方法:
public class EventBusUtil { public static void register(Object subscriber) { EventBus.getDefault().register(subscriber); } public static void unregister(Object subscriber) { EventBus.getDefault().unregister(subscriber); } public static void sendEvent(Event event) { EventBus.getDefault().post(event); } public static void sendStickyEvent(Event event) { EventBus.getDefault().postSticky(event); } // 其他 }
在BaseActivity/BaseFragment
中的onCreate
和onDestroy
方法中订阅和取消订阅,这里添加了一个isRegisterEventBus()
方法,默认返回false
,即不订阅EventBus
,子类Activity/Fragment
如果需要订阅的话复写这个方法并返回true
即可。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (isRegisterEventBus()) { EventBusUtil.register(this); } } /** * 是否注册事件分发 * * @return true绑定EventBus事件分发,默认不绑定,子类需要绑定的话复写此方法返回true. */ protected boolean isRegisterEventBus() { return false; } @Override public void onDestroy() { super.onDestroy(); if (isRegisterEventBus()) { EventBusUtil.unregister(this); } }
定义事件Event
:
public class Event<T> { private int code; private T data; public Event(int code) { this.code = code; } public Event(int code, T data) { this.code = code; this.data = data; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public T getData() { return data; } public void setData(T data) { this.data = data; } }
通过泛型<T>
指定事件通信过程中的数据类型,code
为事件码,使用的时候给不同的事件类型指定不同的code
。
在BaseActivity\BaseFragment
中添加接收到EventBus
的方法:
/** * 是否注册事件分发 * * @return true绑定EventBus事件分发,默认不绑定,子类需要绑定的话复写此方法返回true. */ protected boolean isRegisterEventBus() { return false; } @Subscribe(threadMode = ThreadMode.MAIN) public void onEventBusCome(Event event) { if (event != null) { receiveEvent(event); } } @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) public void onStickyEventBusCome(Event event) { if (event != null) { receiveStickyEvent(event); } } /** * 接收到分发到事件 * * @param event 事件 */ protected void receiveEvent(Event event) { } /** * 接受到分发的粘性事件 * * @param event 粘性事件 */ protected void receiveStickyEvent(Event event) { }
根据自己项目的需求,在订阅了EventBus
的Activity/Fragment
中复写receiveEvent(Event event)
或receiveStickyEvent(Event event)
来处理接收到事件后的逻辑。
这里也可以不用在BaseActivty/BaseFragment
中添加接受事件的方法(因为添加了过后不能确定的子类的Event
泛型)。那么就直接在订阅的Activity/Fragment
中给接收事件的方法添加EventBus
对应的事件接受注解,并指定参数Event的泛型。
@Subscribe(threadMode = ThreadMode.MAIN) public void onEventReceived(Event<User> event) { if (event != null && event.getCode() == C.EventCode.C) { User user = event.getData(); } }
在给定Event
的code
的时候最好在常量池中定义一个类专门用来定义不同类型的EventBus
的code
,这样在接收到EventBus
的地方可以根据这些code
值来判断Event
的来源。
public final class C { // EventBus Code public static final class EventCode { public static final int A = 0x111111; public static final int B = 0x222222; public static final int C = 0x333333; public static final int D = 0x444444; // other more } }
使用示例:
在MainActivity
中复写isRegisterEventBus()
并返回true
注册EventBus
,复写receiveEvent(Event event)
接收发布的事件。
@Override protected boolean isRegisterEventBus() { return true; } @Override protected void receiveEvent(Event event) { // 接受到Event后的相关逻辑 switch (event.getCode()) { case C.EventCode.A: Log.d("EventBus", "接收到A类型的Event"); break; case C.EventCode.B: Log.d("EventBus", "接收到B类型的Event"); break; case C.EventCode.C: Log.d("EventBus", "接收到B类型的Event,携带User"); User user = (User) event.getData(); break; case C.EventCode.D: Log.d("EventBus", "接收到D类型的Event,携带News"); News news = (News) event.getData(); break; } }
在receiveEvent(Event event)
根据对应的事件的code
,判断通信的数据来源和传递的数据类型,以完成对应的逻辑。
在InfoActivity
中发送事件,InfoActivity
只发送不需要接收Event
的话就不注册,也不用复写isRegisterEventBus()
和receiveEvent(Event event)
方法了。
public void sendEventA(View view) { EventBusUtil.sendEvent(new Event(C.EventCode.A)); } public void sendEventB(View view) { EventBusUtil.sendEvent(new Event(C.EventCode.B)); } public void sendEventC(View view) { Event<User> event = new Event<>(C.EventCode.C, new User()); EventBusUtil.sendEvent(event); } public void sendEventD(View view) { Event<News> event = new Event<>(C.EventCode.D, new News()); EventBusUtil.sendEvent(event); }
通过上面的方式,将EventBus
封装到BaseActivity/BaseFragment
中,使得EventBus和项目解耦更加彻底,同时在需要使用的子Activity/Fragment中只需要复写isRegisterEventBus()
和receiveEvent(Event event)
即可,不用每个地方都去订阅和取消订阅。并且给Event
给定code
和泛型能够很好的区分不同的事件来源和数据类型。