RxBus的小试牛刀
来源:互联网 发布:怎样修改游戏数据 编辑:程序博客网 时间:2024/06/07 22:10
前言
RxBus并不是框架,而是一种类似观察者的模式。类似效果的还有EventBus和otto,
但是如果项目中使用了Rx响应式编程,那么用RxBus这种事件通信可以加深对响应式编程的熟练,以及不需要再引用任何库,它就是一个简单的类:
public class RxBus { private static RxBus sRxBus; private final Subject<Object, Object> mBus; // 注释1:PublishSubject private RxBus() { mBus = new SerializedSubject<>(PublishSubject.create()); } //注释2 // 单例 public static RxBus getInstance() { if (sRxBus == null) { synchronized (RxBus.class) { if (sRxBus == null) { sRxBus = new RxBus(); } } } return sRxBus; } // 提供了一个新的事件 public void post(Object o) { mBus.onNext(o); } // 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者 public <T> Observable<T> toObservable(Class<T> eventType) { return mBus.ofType(eventType); }}
看一下注释1:
PublishSubject 分析
查看源码,有PublishSubject的示例:
PublishSubject<Object> subject = PublishSubject.create();//observer1 will receive all onNext and onCompleted events subject.subscribe(observer1); subject.onNext("one"); subject.onNext("two");//observer2 will only receive "three" and onCompleted subject.subscribe(observer2); subject.onNext("three"); subject.onCompleted();
PublishSubject和 通常用的 Observable.subscribe(observer)或者Observable.subscribe(subscriber)不一样,Observable.subscribe会触发事件,
而PublishSubject.subscribe不会马上触发事件,而是onNext的时候才会触发。
所以订阅的subscriber或者observer 只能收到 它后面的onNext的事件。
看一下注释2:
SerializedSubject 分析
查看源码,有SerializedSubject 有这么一段注释:
Wraps a {@link Subject} so that it is safe to call its various {@code on} methods from different threads. When you use an ordinary {@link Subject} as a {@link Subscriber}, you must take care not to call its {@link Subscriber#onNext} method (or its other {@code on} methods) from multiple threads, as this could lead to non-serialized calls, which violates the Observable contract and creates an ambiguity in the resulting Subject.
意思就是说 你用普通的Subject 发射onNext的时候要注意不能在不同的线程发射,会引发线程安全的。
通常我们用 mySafeSubject = new SerializedSubject( myUnsafeSubject ); 将普通的Subject包裹进SerializedSubject 可以解决线程安全的问题。
继续看SerializedSubject 的源码,看一下它是怎么解决线程安全的问题。
public class SerializedSubject<T, R> extends Subject<T, R> { private final SerializedObserver<T> observer; private final Subject<T, R> actual; public SerializedSubject(final Subject<T, R> actual) { super(new OnSubscribe<R>() { @Override public void call(Subscriber<? super R> child) { actual.unsafeSubscribe(child); } }); this.actual = actual; this.observer = new SerializedObserver<T>(actual); } @Override public void onCompleted() { observer.onCompleted(); } @Override public void onError(Throwable e) { observer.onError(e); }//原来SerializedSubject把onCompleted、onError、onNext都交给了SerializedObserver去处理。 @Override public void onNext(T t) { observer.onNext(t); } @Override public boolean hasObservers() { return actual.hasObservers(); }}
SerializedSubject把onNext交给SerializedObserver去处理了,接着看看SerializedObserver的源码。
SerializedObserver 分析
还是看看源码的注释:
When multiple threads are emitting and/or notifying they will be serialized by:
Allowing only one thread at a time to emit
Adding notifications to a queue if another thread is already emitting
Not holding any locks or blocking any threads while emitting
有道词典翻译加个人理解:只允许onNext在同一时间只能在一个线程发射,
如果已经存在一个线程发射onNext,那么另一个发射onNext将添加到队列中,
在发射onNext过程中,不会持有任何锁和阻塞线程。
贴出SerializedObserver.onNext代码
@Override public void onNext(T t) { if (terminated) { return; } synchronized (this) { if (terminated) { return; } //emitting为true,说明有线程已经正在发射onNext中 if (emitting) { FastList list = queue; if (list == null) { list = new FastList(); queue = list; } //把现在准备要发射的事件加到队列中,然后直接返回 list.add(nl.next(t)); return; } emitting = true; } try { //没有线程在发射onNext就直接 onNext actual.onNext(t); } catch (Throwable e) { terminated = true; Exceptions.throwOrReport(e, actual, t); return; } for (;;) { for (int i = 0; i < MAX_DRAIN_ITERATION; i++) { FastList list; synchronized (this) { list = queue; //如果 队列 是空的,直接返回,发射ing 也置为false if (list == null) { emitting = false; return; } queue = null; } for (Object o : list.array) { if (o == null) { break; } try { //下面分析 //事件为 COMPLETED或者ERROR ,才终止 if (nl.accept(actual, o)) { terminated = true; return; } } catch (Throwable e) { terminated = true; Exceptions.throwIfFatal(e); actual.onError(OnErrorThrowable.addValueAsLastCause(e, t)); return; } } } } }
上面看到了nl.accept(actual, o),跟进去。 看到只有事件为 COMPLETED或者ERROR,才返回true,如果为ON_NEXT,依旧 死循环 for (;;)
public boolean accept(Observer<? super T> o, Object n) { if (n == ON_COMPLETED_SENTINEL) { o.onCompleted(); return true; } else if (n == ON_NEXT_NULL_SENTINEL) { o.onNext(null); return false; } else if (n != null) { if (n.getClass() == OnErrorSentinel.class) { o.onError(((OnErrorSentinel) n).e); return true; } o.onNext((T) n); return false; } else { throw new IllegalArgumentException("The lite notification can not be null"); } }
回到RxBus,发射事件
public void post(Object o) { //bus就是PublishSubject,所以随时发射onNext都可以 mBus.onNext(o); }
回到RxBus,订阅事件
public <T> Observable<T> toObservable(Class<T> eventType) { return mBus.ofType(eventType); }
ofType = filter+cast
public final <R> Observable<R> ofType(final Class<R> klass) { return filter(InternalObservableUtils.isInstanceOf(klass)).cast(klass); }
filter 根据传进来的类过滤,post的时候只发射给对应的订阅者
cast 类型转换
结束
本文是分析源码以及查看资料,然后写的,有哪些地方不对的欢迎指出。
哈哈O(∩_∩)O哈哈~。
- RxBus的小试牛刀
- RxJava+RxBus的使用
- RXBus的翻译
- RXBUS的简单使用
- RxBus的使用示例
- Android Rxbus的使用
- 基于RxJava的RxBus
- rxbus的实现
- Rxbus的简单使用
- Android RxBus的使用
- 超好用的RxBus库
- 基于Rxrelay的RxBus
- RxBus
- RxBus
- RXBUS
- RxBus
- RxBus
- RxBus
- 离线轻量级大数据平台Spark之MLib机器学习库朴素贝叶斯实例
- mysql总结
- myeclispe快捷键
- 微信分享 微信对图片文字大小的限制 代码如下
- 事件分发机制
- RxBus的小试牛刀
- 1119. Pre- and Post-order Traversals (30)
- Android 自定义View (一)
- bzoj 1047 理想的正方形
- java基础面试题1-----String,StringBuffer,StringBuilder的区别
- Xcode 8制作动态及静态Framework
- 微信公众号网页上点击放大图片浏览,解决方案
- angularJS之项目知识
- maven 打包时,总是少了一个包,后来发现是pom 文件的scope 的类型导致