观察者模式
Rx的设计模式其实就是一种变相的 观察者模式,所以我们必须得先了解下标准的观察者模式
这就是标准的观察者模式。很简单
Rx Hook
问题:如果我的整个项目都使用了Rxjava ,那么我怎么监听全局Rx呢
首先看一段代码:
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
}
})
.map(new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
return null;
}
})
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(String s) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
代码没啥好说的,很简单,我们在 .create 的时候会给我们返回一个new ObservableCreate,在 .map的时候返回的是new ObservableMap ....我们需要的就是在这个过程中拦截。如图
那么中间区域到底是什么呢?我们来看下源码 ?点进create 发现
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
中间区域 就是 onAssembly 也就是我们的全局hook 如果点进map 也是一样的
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
ObjectHelper.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
}
点进onAssembly 进去
public static <T> Observable<T> onAssembly(@NonNull Observable<T> source) {
Function<? super Observable, ? extends Observable> f = onObservableAssembly;
if (f != null) {
return apply(f, source);
}
return source;
onObservableAssembly 默认为null 所以这个相当于啥都没做。。。 那我们在跟一下onObservableAssembly 赋值的地方看一下
/**
* Sets the specific hook function.
* @param onObservableAssembly the hook function to set, null allowed
*/
@SuppressWarnings("rawtypes")
public static void setOnObservableAssembly(@Nullable Function<? super Observable, ? extends Observable> onObservableAssembly) {
if (lockdown) {
throw new IllegalStateException("Plugins can't be changed anymore");
}
RxJavaPlugins.onObservableAssembly = onObservableAssembly;
}
看注释写的很清楚 设置指定的hook函数 所以 只要我们调用这个函数 设置我们自己的function就可以实现拦截全局的rx了
RxJavaPlugins.setOnObservableAssembly(new Function<Observable, Observable>() {
@Override
public Observable apply(Observable observable) throws Exception {
//这里就可以拦截了
//返回null的话 会导致后面所有用到rx的地方空指针
return observable;
}
});
Rx 观察者模式
分为三步 第一、创建Observable,第二、创建Observer、第三、使用subcribe()订阅
首先看Observer源码
public interface Observer<T> {
/**
* Provides the Observer with the means of cancelling (disposing) the
* connection (channel) with the Observable in both
* synchronous (from within {@link #onNext(Object)}) and asynchronous manner.
* @param d the Disposable instance whose {@link Disposable#dispose()} can
* be called anytime to cancel the connection
* @since 2.0
*/
void onSubscribe(@NonNull Disposable d);
/**
* Provides the Observer with a new item to observe.
* <p>
* The {@link Observable} may call this method 0 or more times.
* <p>
* The {@code Observable} will not call this method again after it calls either {@link #onComplete} or
* {@link #onError}.
*
* @param t
* the item emitted by the Observable
*/
void onNext(@NonNull T t);
/**
* Notifies the Observer that the {@link Observable} has experienced an error condition.
* <p>
* If the {@link Observable} calls this method, it will not thereafter call {@link #onNext} or
* {@link #onComplete}.
*
* @param e
* the exception encountered by the Observable
*/
void onError(@NonNull Throwable e);
/**
* Notifies the Observer that the {@link Observable} has finished sending push-based notifications.
* <p>
* The {@link Observable} will not call this method if it calls {@link #onError}.
*/
void onComplete();
}
可以看到 就是一个接口而已,真正的实现 是我们的实现的
看Observable的源码
刚才已经看过了Observable.create源码了
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
可以看到 传入的参数 就是我们传入的自定义的source
订阅流程分析
点进subscribe() 可以看到
@SchedulerSupport(SchedulerSupport.NONE)
@Override
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
subscribeActual(observer);
} catch (NullPointerException e) { // NOPMD
throw e;
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
// can't call onError because no way to know if a Disposable has been set or not
// can't call onSubscribe because the call might have set a Subscription already
RxJavaPlugins.onError(e);
NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
npe.initCause(e);
throw npe;
}
}
可以看到里面的 有效代码只有 subscribeActual(observer); 点进去发现 这是个抽象方法,由于.subscribe() 实际上是ObservableCreate. subscribe() 的,create一执行完成就会返回ObservableCreate对象。 所以 subscribeActual的实现肯定在ObservableCreate里
@Override
protected void subscribeActual(Observer<? super T> observer) {
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
observer.onSubscribe(parent);
try {
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
可以看到 new了一个发射器包装了我们传进来的observer 然后自定义的source调用了 subscribe(),这样两端就联系起来了,看下整体流程
整体就是一个U型的结构
两者的区别
普通的观察者模式: 一个被观察者 对应多个观察者 被观察者发出改变通知 所有的观察者改变
Rx的观察者模式:多个被观察者对应一个观察者 并且需要起点和终点再订阅一次之后 才发出通知改变,终点才改变
map操作符的原理
示例代码:
// ObseravbleCreate 自定义source传递进去了 == source
Observable.create(
// 自定义source
new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
}
})
// ObseravbleCreate.map
.map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(String s) throws Exception {
return null;
}
})
// ObservableMap.subscribe
.subscribe(
// 自定义观察者(终点)
new Observer<Bitmap>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Bitmap bitmap) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
同样的 我们来看下流程
可以看到 和订阅流程类似 只是多了一个 封包裹 和拆包裹的过程
这是一个洋葱模型 (封包裹-> 拆包裹)
事实上Rx还用了一个装饰模式
大概就是这样的模型
那么其实 Rx也不算是标准的u型结构 而是:
类似于下单买东西--->封包裹--->拆包裹