java响应式编程框架_RXJava2响应式编程框架设计<四>---高阶泛型、手写RxJava2核心实现...

在之前三篇中已经对于RxJava2的各种使用及原理有了一定的了解了,接下来则通过手写实现的方式加强对于它的原理的掌握。

extend T>和 super T>阐述:

从是否可读可写角度说明:

在正式手写RxJava代码之前,需要先对其泛型知识做一个巩固,因为RxJava的源码中充斥着大量的泛型,先来贴一个源码中的一处代码:

f715bb4c07ff2886540dbaac29860e5e.png

其实核心就是要了解 extend T>和 super T>的使用场景,关于这块在当时学习Kolin时已经阐述得非常之清楚了,可以参考https://www.cnblogs.com/webor2006/p/11291744.html,总结一下就是 extend T>是协变,只能读,而 super T>是逆变,只能写。

说到这俩个泛型的区别,我记得在面试时问到候选人这个问题,基本上9成的回答是:“ extend T>代表只能传T的子类型; super T>代表只能传T的父类型。。”,这个回答等于把人当傻子,是个人看到都能说出这点,extend和super从编程语义上也能知道嘛,但是好的回答应该是从使用场景来道出这俩的不同以及怎么使用。

由于之前已经对于这块详细说明过,这里再简单的过一下,温故而知新~~

6787cb5bdd70e437975413c6168236c4.png

44016d41b43f3ded24455d9f72dc36fc.png

而如果修改一下:

6cffcbcd5963668602fdc984cea8dd6c.png

再来修改:

143d52ae14f0aef09cef23fabe14598a.png

当然可以强制转换倒是可以:

7e5aebf72aee93d7a8771542e0e62152.png

接着咱们添加试一下:

0ab3077c3650bd898f76e8a3fb135d6a.png

从函数定义角度说明:

extend T>,只能读不能写,很显然适合作为方法的返回值,比如:

31cb008291889df3ce947b26878d9c7e.png

super T>,只能写不能值,那适合当参数传递,如下:

9622f0e12959820defbe1ece26f683dd.png

总结:

如果你想从一个数据类型里获取数据,使用 ? extends 通配符(能取不能存)

如果你想把对象写入一个数据结构里,使用 ? super 通配符(能存不能取)

如果你既想存,又想取,那就别用通配符。

手写RxJava2核心实现:

接下来开启又兴奋又刺激的手撸环节:

框架搭建:

先来建一个文件夹,里面用来存放我们写手的RxJava框架代码:

4bc01d1908c4a9ff5944600739a773ef.png

然后先来定义一个被观察者类:

a873077b903e1b610dd25da20cae3e58.png

而看一下RxJava的源码,它其实是实现了一个接口的,如下:

b4167a3b8675571b48e51fa590b38df4.png

bad82878bb7c829c8ad62417eeada239.png

所以校仿一下:

d73b658c4ac21b3f0428a84d207b8576.png

这里为啥是要 super T>,很明显是要将它做为参数传递的,接下来咱们来定义观察者,也是个接口:

a3457025a1c187a11a84b7a173e084bb.png

packagecom.android.rxjavastudy;importcom.android.rxjavastudy.rxjava.Disposable;public interface Observer{voidonSubscribe(Disposable d);voidonNext(T t);voidonError(Throwable e);voidonComplete();

}

其中需要一个Disposable,它也是一个接口,定义如下:

62ff627b9b64287e938ed2236cb5463a.png

packagecom.android.rxjavastudy.rxjava;public interfaceDisposable {void dispose(booleanbool);booleanisDisposed();

}

Observable.create():

接下来则来实现一下创建被观察者的逻辑,如下:

eabc37278e34ecfbf87782980560ea71.png

先来看一下它的定义,然后咱们再校仿一下:

e9d7c766591ef89f8f03a320d0f15771.png

咱们校仿着定义一下,其中勾子函数的代码一并忽略:

7f510c6b6bb79f0164609641f324d711.png

先来看一下源代码的定义:

d5733d7f5ff6d7359609090459540f8f.png

校仿一下:

c1b850d05816dabf63c0e7b41f24b881.png

这里又来参考下源代码的定义:

10794b31c8a240068a65c53254f8a04f.png

08b9ef5c38fd96a067e6a76830d8e78f.png

所以接下来定义两个跟发射器相关的接口:

17af38db13ca14b3471f89afb97488f9.png

46478b0050cb92712d730f869ba3264f.png

好,接下来则再来定义这个类:

c2ad50ffed0a5cb6361c91c2b1081e30.png

97d475ed6b3aed0298ad7a6f089e6cf7.png

此时咱们就可以调用咱们自己的编写的RxJava代码了,如下:

deb8c7ba63f3e7904e53a28c595d47ba.png

这里要来明白一种思想就是:

9c8c87de97aff4bf9c6569af0bcba8ab.png

其实它里面是做了转换了的:

71eddba36d27603dc5c29f564194f8d9.png

也就是对于源来的功能通过装饰则对原功能进行了加强。

订阅逻辑实现(subscribe):

接下来则要来实现最核心的订阅方法啦,也就是:

77c0335a12bd4efcdb5bad49274a770e.png

c33dda60c38d1071b8b6cf87439b0b4d.png

那它里面该怎么实现呢?依然先看源码:

404516649596d30e0c40e76591cb1c78.png

所以照抄一下:

2314afd14af6d904094c5dce3300fad6.png

所以在ObservableCreate()中来具体实现之:

cb73e5785b278f045297ec0107399ff5.png

a93937dba0e98403dafab3860f3502f4.png

注意在子类中就木有必要重写subscribe()方法了,它统一由父类Observable来进行管理,那具体在子类中怎么来实现呢?

首先可以回调一下订阅成功的回调:

4c35df219512946f1c7875e1becdcd2e.png

这里则需要再定义一下,在里面定义成一个内部类,如下:

public class ObservableCreate extends Observable{final ObservableOnSubscribesource;public ObservableCreate(ObservableOnSubscribesource) {this.source =source;

}

@Overrideprotected void subscribeActual(Observer super T>observer) {

CreateEmitter parent = new CreateEmitter<>(observer);

observer.onSubscribe(parent);

}static final class CreateEmitter implements ObservableEmitter, Disposable {

final Observer super T> observer;

private boolean bool;

public CreateEmitter(Observer super T> observer) {

this.observer = observer;

}

@Override

public void dispose(boolean bool) {

this.bool = bool;

}

@Override

public boolean isDisposed() {

return bool;

}

@Override

public void onNext(T value) {

if (!bool) {

observer.onNext(value); //observer === MapObserver

}

}

@Override

public void onError(Throwable throwable) {

if (!bool) {

observer.onError(throwable);

}

}

@Override

public void onComplete() {

if (!bool) {

observer.onComplete();

}

}

}

}

此时则会回调咱们的这个应用回调接口了:

3c0a0191db5e93d973cfff44dad8be5a.png

好,接下来则应该来回调待观察者的回调方法,来对事件进行发送:

2040120109f7b3ba205c5f75d74f1b6c.png

怎么调用呢?比较简单:

5191fa8671e8e9515857bc1eb0b0824b.png

此时我们调用发射器的方法:

13fcf654f27c8d2caeeeec3065db4ac8.png

最终就是直接通过了我们在这定义的发射器的方法:

d3ef8b4120296c1173df2940fe1d6b6f.png

再转向到了我们的观察者的回调了:

629efe587ec3eb68c1f9b2f9fcc5fb36.png

原来是这么个流程,手写了一遍确实顺间另深了对RxJava调用流程的理解了。

运行看一下调用效果:

目前就可以来看一下调用效果了:

cccaec523b0b092c327d266afd20c1b5.png

加入map操作符复杂实现:

在上面的实现中是一个最为简单的版本,这次准备实现一个map操作符的效果,最终效果如下:

d91586e97b5393fef127c0e399840803.png

别看只是简单的增加一个操作符,便是实际它内部实现也不是很简单的,下面开始:

757e1c4491704b19e08d53368d497a78.png

新的一个操作符里面肯定又得重新封装一下,那具体怎么封装呢?先看一下源码的实现:

6a1cbac1ecca9ee33ba7c90d5d670e9b.png

ce831ebe93ff2ca31247e3f6d619f4cf.png

5f29effbfb8d84580e2976ff823311c2.png

校仿一下,先来定义一个抽象类:

6ec045c9303403d14e43d8eebd5c9408.png

4756db52305d2312cffd53fc0254271d.png

然后再来定义ObservableMap:

b209cf71172cbf66676d299848ea0f39.png

packagecom.android.rxjavastudy.rxjava;public class ObservableMap extends AbstractObservableWithUpstream{final Function super T, ? extends U>function;public ObservableMap(ObserverbleSource source, Function super T, ? extends U>function) {super(source);this.function =function;

}

@Overrideprotected void subscribeActual(Observer super U>observer) {//TODO

}

}

接下来则来生成这个包装类:

ad8105b7174c55d39b4b96085d1ae793.png

Function定义如下:

776336113808b2d628eb565199498b73.png

接下来则来实现ObservableMap这个被观察者的订阅方法,首先肯定也得先回调一下观察者的订阅成功的方法啦:

b3ab52d261cb7d3e7717daf93bf1cdd3.png

但是这里改变写法了,先来看一下源码这块的实现,可以参考一下:

dca867d694e0f3461b2b7bfa80db0ad9.png

其实回调观察者的订阅方法是放到了内部类的父类了,如下:

e23dadcebc52c9e552747e787ed9e617.png

c540da7a9442c987c0b5d31d74e75689.png

所以,校仿一下:

77bfe0b1e66f02096d9b1f957814f6c2.png

ec941506eca0041b13635a7210bbb0c4.png

packagecom.android.rxjavastudy.rxjava;//观察者

public abstract class BasicFuseableObserver implements Observer, Disposable{//观察者

protected final Observer super R>actual;protectedDisposable disposeble;public BasicFuseableObserver(Observer super R>actual) {this.actual =actual;

}

@Overridepublic voidonSubscribe(Disposable d) {this.disposeble =d;

actual.onSubscribe(d);

}

@Overridepublic voidonError(Throwable e) {

actual.onError(e);

}

@Overridepublic voidonComplete() {

actual.onComplete();

}

@Overridepublic void dispose(booleanbool) {

disposeble.dispose(bool);

}

@Overridepublic booleanisDisposed() {returndisposeble.isDisposed();

}

}

注意此时的source是调用onCreate()操作符生成的被观察者,也就是ObservableCreate, 所以当调用:

70a3aebec1da99278f5d24067e2712ff.png

则会转到它:

a29b72a43ac62ef79ab6fb6d7825c7a4.png

99856e3bc1992281abe1f093e7aea41e.png

最后再又执行到了被观察者的事件回调方法:

09e37aba6574ce3f3b3e9901500d0e61.png

好了,整个map操作符的代码就写完了,还是挺绕的,接下来咱们应用一下看下效果:

d0f8069d703b84fc02a38413c7c7d9d1.png

运行结果:

7cd9b7751e5f2dae7152dfee7ae5e2e2.png

线程切换:

接下来则来完成一下线程的切换功能,我们之前已经清楚的知道了:

1713af8522fb18a932adb34261be658a.png

那对于map转换操作符是在哪个线程呢?其实它跟被观察者的回调是在同一个线程的,下面来打印一下验证一下:

ddae71842add4b436844dc97c501562d.png

运行:

fcebdc5dbe1d2de490faae89bc55cddc.png

确实map操作符跟被观察者的事件回调都是由subscribeOn来决定的线程,下面则来实现一下线程切换。

subscribeOn():

首先先来在观察者中定义这个方法:

b5b4c7ce20ce2d2528eacc3a9f327d9f.png

此时咱们就给这个方法定义参数了,默认就让它在io线程里,先来调用一下它:

b15221399bdee775c86627f9ea568ea8.png

如之前的套路一样,这是一个新的操作符,又得做个被观察者的装饰,所以新建一个:

5040c07fea5fa5d522a1243e601abc34.png

5b958e1ebc3919da3f245f5482084f5b.png

所以此时就可以实例化它了:

6d386d4b097daf59dee1e4f86ea9c6c9.png

接下来则来处理包装被观察者的实现逻辑了,首先还是得先告诉观察者已经订阅成功了,又得有个观察者的包装,老套路如下:

packagecom.android.rxjavastudy.rxjava.observable;importcom.android.rxjavastudy.rxjava.Disposable;importcom.android.rxjavastudy.rxjava.Observer;importcom.android.rxjavastudy.rxjava.ObserverbleSource;//指定被观察者在那个线程运行的被观察者

public class ObservableSubscribeOn extends AbstractObservableWithUpstream{public ObservableSubscribeOn(ObserverbleSourcesource) {super(source);

}

@Overrideprotected void subscribeActual(Observer super T>observer) {//重新包装observer

final SubscribeOnObserver parent = new SubscribeOnObserver(observer);

//告诉下游观察者订阅成功observer.onSubscribe(parent);

}static final class SubscribeOnObserver implements Observer, Disposable {

final Observer super T> actual;

Disposable disposable;

public SubscribeOnObserver(Observer super T> actual) {

this.actual = actual;

}

@Override

public void dispose(boolean bool) {

this.disposable.dispose(bool);

}

@Override

public boolean isDisposed() {

return this.disposable.isDisposed();

}

@Override

public void onSubscribe(Disposable d) {

this.disposable = d;

}

@Override

public void onNext(T t) {

this.actual.onNext(t);

}

@Override

public void onError(Throwable e) {

this.actual.onError(e);

}

@Override

public void onComplete() {

this.actual.onComplete();

}

}

}

好,接下来就应该是回调被观察者的事件方法了,注意!!此时就需要进行线程的切换了,如下:

e72cace6cb52d753ff6654977bd96ade.png

于此关于这个方法的逻辑就实现完了,是不是也不是很难?此时我们的map肯定也是在子线程啦,为啥?

c2aa34dcf666a8ec5f4804b0ec4fa3a6.png

eb52a251699a671d72c3199fa84527a3.png

好,接下来咱们来验证一下是否已经实现了此功能了:

c0f1a50e57a87827e507e2b87baae80c.png

运行:

87a0c2094412594f37b67d5213b6b953.png

但是!!此时next()回调的线程不对呀:

29fc426cb8ca28e3f91a8218a41d3c18.png

这是因为我们还没有实现observeOn(),所以接下来再来实现它。

observeOn():

同样的套路,就不多说了,直接贴出实现:

d8577ea4abb13bf27a62be9e2de5d38e.png

packagecom.android.rxjavastudy.rxjava.observable;importandroid.os.Handler;importandroid.os.Looper;importcom.android.rxjavastudy.rxjava.Disposable;importcom.android.rxjavastudy.rxjava.Observer;importcom.android.rxjavastudy.rxjava.ObserverbleSource;//指定观察者在那个线程运行的被观察者

public class ObservableObserveOn extends AbstractObservableWithUpstream{public ObservableObserveOn(ObserverbleSourcesource) {super(source);

}

@Overrideprotected void subscribeActual(Observer super T>observer) {

ObserverOnObserver parent = new ObserverOnObserver<>(observer);

source.subscribe(parent);

}//包装下游观察者,并关联onNext,..... 放入主线程中执行

static final class ObserverOnObserver implements Observer, Disposable {final Observer super T>actual;

Disposable disposeble;privateHandler handler;

ObserverOnObserver(Observer super T>actual) {this.actual =actual;

handler= newHandler(Looper.getMainLooper());

}

@Overridepublic void dispose(booleanbool) {this.disposeble.dispose(bool);

}

@Overridepublic booleanisDisposed() {return this.disposeble.isDisposed();

}

@Overridepublic voidonSubscribe(Disposable d) {this.disposeble =d;

actual.onSubscribe(d);

}

@Overridepublic void onNext(finalT t) {

handler.post(new Runnable() {

@Override

public voidrun() {

actual.onNext(t);

}

});

}

@Overridepublic void onError(finalThrowable e) {

handler.post(new Runnable() {

@Override

public voidrun() {

actual.onError(e);

}

});

}

@Overridepublic voidonComplete() {

handler.post(new Runnable() {

@Override

public voidrun() {

actual.onComplete();

}

});

}

}

}

嗯,比较简单,再来应用一下:

4b9ffbe1f9a7ef16d8672619e6f60116.png

运行:

3e61e0e4fa021d6ea9ff1e01e9dc7c27.png

至此,手写RxJava的核心功能就到这,对它的原理了解得也更加透彻了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值