相信大家在进行Android开发的时候最头疼的就是这边有一个点击事件,需要传递到其他界面显示结果,或者说有一处变化了需要告诉许多界面去刷新界面。相信经常使用Fragment进行开发的小伙伴们经常会遇到Fragment界面相互影响,相互刷新的各种负责的业务。这些都是我们需要使用到事件通知的场景。
最初我们使用的是Android自身携带的广播Broadcast来解决这个问题,在需要接收的地方注册广播接收监听,然后通过context.sendBroadcast来发送事件,通过Intent来传递数据。这种如果在最初使用的话还是比较简单的,但是如果需要通知的事件多了的话,整个项目里面就都是sendBroadcast以及registerReceiver,广播使用得不好还很容易出现内存泄露,代码的逻辑性以及程序的稳定性将会大打折扣,使用起来也是极其不方便。
后来学习了java的设计模式之观察者模式,自己设计了一套事件通知工具,其实质还是“接口回调监听“,使用起来可以说比广播好了多了,但是嘛,在使用的过程中还是会出现这些或者那些的问题,最主要的问题就是接口回调不能给自由地切换线程,在子线程回调出来的就是子线程,在主线程回调出来的就是主线程,不好进行线程控制。这也是为什么之前EventBus事件工具如此火的原因所在,它可以控制事件触发的子线程还是主线程。
但是仅仅是EventBus根本满足不了我对代码简洁、使用方便、安全的要求。我理想中的事件工具应该是这样的:只需一行代码就可以完成事件动作的注册、只需一行代码就可以完成事件的传递、只需一行代码就可以轻松地注销事件监听,并且可以自由地控制线程,而串联这三个的只需要一个事件TAG即可,后面只需要维护这个事件TAG就行了。不需要像EventBus那样在每个Activity或者Fragment里面写onEventMainThread这种笨笨的代码。那么这样的事件工具真的有吗?当然有啦,那就是接下来我要隆重地推荐以及介绍的RxBus!
RxBus顾名思义是基于RxJava这个目前火得不能再火的项目改造而成的,RxBus继承了RxJava的最大特性:变化【转化】,通过它我们可以轻松地进行线程控制,代码也起来也是极其简洁明了。RxBus的代码很简洁,只有一个java类,如下:
/** * RxBus * * @author xx * */ public class RxBus { private ConcurrentHashMap<Object, List> maps = new ConcurrentHashMap<Object, List>(); private static RxBus sInstance; public static RxBus get() { if (sInstance == null) { synchronized (RxBus.class) { if (sInstance == null) { sInstance = new RxBus(); } } } return sInstance; } /** * 简单以对象的类名注册 * @param o * @return */ public Observable simpleRegister(@NonNull Object o) { return register(o.getClass().getSimpleName()); } /** * 注册订阅 * @param tag * @return */ public Observable register(@NonNull Object tag) { List subjects = maps.get(tag); if (subjects == null) { subjects = new ArrayList(); maps.put(tag, subjects); } Subject subject = PublishSubject. create(); subjects.add(subject); return subject; } /** * 注销tag制定的订阅 * @param tag */ public void unregister(@NonNull Object tag, @NonNull Observable observable) { List subjects = maps.get(tag); if (subjects != null) { subjects.remove((Subject) observable); if (subjects.isEmpty()) { maps.remove(tag); } } } /** * 注销tag所有的订阅 * @param tag */ public void unregisterAll(@NonNull Object tag) { List subjects = maps.get(tag); if (subjects != null) { maps.remove(tag); } } public void post(@NonNull Object tag) { post(tag, tag); } /** * 发送指定tag的事件 * @param tag * @param o */ @SuppressWarnings("unchecked") public void post(@NonNull Object tag, @NonNull Object o) { List subjects = maps.get(tag); if (subjects != null && !subjects.isEmpty()) { for (Subject s : subjects) { s.onNext(o); } } } } public class RxManager { private final static String TAG = "RxManager"; private static RxManager sInstance; private RxBus mRxBus = RxBus.get(); /** 管理Subscribers订阅,防止内存泄漏 */ private ConcurrentHashMap maps = new ConcurrentHashMap(); public static RxManager get() { if (sInstance == null) { synchronized (RxManager.class) { if (sInstance == null) { sInstance = new RxManager(); } } } return sInstance; } /** * * RxBus注入监听 * * @param eventName * * @param action1 */ public void onMainThread(Object eventName, Action1 action1) { Observable Observable = mRxBus.register(eventName); /* 订阅管理 */ add(eventName, Observable.observeOn(AndroidSchedulers.mainThread()).subscribe(action1, new Action1() { @Override public void call(Throwable throwable) { Log.e(TAG, throwable.getMessage()); } })); } /** * * RxBus注入监听 * * @param eventName * 事件名 * @param action1 */ public void on(Object eventName, Action1 action1) { Observable Observable = mRxBus.register(eventName); /* 订阅管理 */ add(eventName, Observable.subscribe(action1, new Action1() { @Override public void call(Throwable throwable) { Log.e(TAG, throwable.getMessage()); } })); } /** * 单纯的Observables 和Subscribers管理 * * @param m */ public void add(Object eventName, Subscription m) { /* 订阅管理 */ CompositeSubscription subscription = maps.get(eventName); if (subscription == null) { subscription = new CompositeSubscription(); maps.put(eventName, subscription); } subscription.add(m); } /** * * 单个presenter生命周期结束,取消订阅和所有rxbus观察 */ public void clear(@NonNull Object eventName) { CompositeSubscription subscription = maps.get(eventName); if (subscription != null) { subscription.unsubscribe(); // 取消订阅 maps.remove(eventName); } mRxBus.unregisterAll(eventName); } // 发送rxbus public void post(Object tag) { mRxBus.post(tag); } // 发送rxbus public void post(Object tag, Object content) { mRxBus.post(tag, content); } }
这里我就不具体阐述RxBus以及RxManager是如何起到事件通知的效果的,想了解的可以自行去了解Rxjava的特性。
这里我只介绍如何使用RxBus。
1、首先是事件动作注册:
RxManager.get().on注册的事件回调后返回的还是当前的线程,RxManager.get().onMainThread注册的事件回调后返回的直接是主线程。
2、其次是事件的通知:
直接调用RxManager.get().post(Event_Key) :不携带数据的事件
RxManager.get().post(Event_Key,object) :携带数据的事件
3、最后就是事件监听的销毁:
直接调用RxManager.get().clear(Event_Key)即可。
以上三部即可完成事件通知的全过程,是不是很方便啊,O(∩_∩)O~~,实在是太给力了!