前言
现在有很多公司在用RXJava进行生产开发,但是呢,RXJava的源码过于生涩难懂,而且用法也很多,操作符也很多,因此本文手写一个精简版的RXJava,希望能够一起去探索,RXJava在安卓中的奥妙!注意:本篇读者需要对RXJava有一定的使用经验与对RXJava调用过程有一定的理解
一、RXJava常用写法
io.reactivex.rxjava3.core.Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Throwable {
//被观察者产生事件
}
}).map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Throwable {
//事件的转换
return null;
}
}).subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribe(new io.reactivex.rxjava3.core.Observer<Integer>() {
//观察者处理事件
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull Integer integer) {
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
});
我们可以看到上述的代码,用到的操作有create,map,subscribe,subscribeOn,observeOn这几个。那么我们直接去从源码角度去解析。
public static <T> Observable<T> create(@NonNull ObservableOnSubscribe<T> source) {
Objects.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<>(source));
}
很多人看到这里就是一脸懵逼,其实RXJava的很多操作符都是采用这种方式去实现的,我们可以注意到这个方法里里面new 了一个ObservableCreate<>(source)对象,其实呢,这个就相当于一个包装类,那么它包装了什么呢,我们看类的关系
可以看到,其实就是对Obserable进行了一层包装。返回的ObservableCreate对象我们可以先视为Obserable对象,这点很重要。
那么为什么要返回一个与Obserable相关的对象呢?原因就是RXJava采用的链式编程,想要通过.操作链式操作吗,那么返回的要么是本类的this指针,要么是new一个对象。而RXJava采用了后者,这样保持了操作层次间的隔阂,因为.后一个Obserable不知道.前一个Obserable具体进行了什么操作,这样就很有利于层次的隔离。
create操作简单来看,也就是返回了用户建立的Obserable对象的包装类,这里不明白的话我们可以看到手写RXJava的环节,在那里我们去除相关的包装操作,更加方便我们去理解。
map操作其实和create的形式差不多
public final <R> Observable<R> map(@NonNull Function<? super T, ? extends R> mapper) {
Objects.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new ObservableMap<>(this, mapper));
}
点进去onAssembly里面看,不过map里面有自己需要处理的逻辑,就是转换这个操作
@NonNull
static <T, R> R apply(@NonNull Function<T, R> f, @NonNull T t) {
try {
return f.apply(t);
} catch (Throwable ex) {
throw ExceptionHelper.wrapOrThrow(ex);
}
}
最终会调用用户自己写入的apply方法。因为RXJava只是提供一个模式给用户,不负责处理具体的逻辑。
其他的异步操作代码形式相同,不过却有着自己的实现逻辑,我们先不分析其他的,直接进入到手写RXJava的逻辑吧!
二、手写RXJava
通过之前的代码分析,我们应该有一个模糊的了解,就是RXJava的链式调用采用的是new一个对象返回,而不是简单返回this指针,因此我们有如下代码
这里建立一个被观察者类
public abstract class Observable<T> {
/*
该方法是模拟Rxjava中的create方法,实际上Rxjava是做了一层包装
*/
public static <T> Observable<T> create(Observable<T> observable) {
//用户给什么,我们就返回什么,就是这么任性
return observable;
}
public abstract void subscribe(Observer<T> observer);
}
这里声明一个观察者接口,里面的方法实现由使用者自行设定
public interface Observer<T> {
void onNext(T parms);
void onComplete();
void onError();
}
这样子,我们就已经是实现好了一个简单的create操作符,是不是很神奇
//create方法
Observable.create(new Observable<String>() {
@Override
public void subscribe(Observer<String> observer) {
}
}).subscribe(new Observer<String>() {
@Override
public void onNext(String parms) {
}
@Override
public void onComplete() {
}
@Override
public void onError() {
}
});
和RXJava一摸一样吧,能够实现这样的效果的原因就是用户重写的Observer方法会被事件分发的时候调用。请读者一定要理解这个过程,因为后面的操作符就是基于这个过程来实现的。
接下就是map操作符
设定一个数据转换接口,具体实现有用户实现
public interface Funtion<T,R> {
R transform(T t);
}
public <R> Observable<R> map(Funtion<T, R> funtion) {
return new Observable<R>() {
@Override
public void subscribe(Observer<R> observer) {
Observer<T> observerNext = new Observer<T>() {
@Override
public void onNext(T parms) {
R transform = funtion.transform(parms);
observer.onNext(transform);
}
@Override
public void onComplete() {
observer.onComplete();
}
@Override
public void onError() {
observer.onError();
}
};
//将本次创建的Observe给上一轮的OObservable
Observable.this.subscribe(observerNext);
}
};
}
这里的难点有3个
1.new Observable()作用是:因为RXJava也是采用new一个新对象的方式返回的,所以我们仿照这形式即可,上文也说到,其实操作符返回的类都是Observable的子类,进行了各自功能的包装,因此我们直接new一个返回即可。
2.observerNext是什么,其实就是new出来的Observable的观察者对象。这里有一个细节需要我们去注意,就是new出的Observable对象的public void subscribe(Observer observer)方法,其实这个方法涉及到了RXJava的流程,大致分为订阅、观察者上溯、事件分发三个过程,这里就不列举相关的图片了,太复杂没有必要列举。
大家只要知道,这个方法传过来的observer对象,就是我们实际调用的时候的observer对象
3.通过上面两点,我们Observable之间并没有完全建立联系,因为Observable有多个,我们new出来的就有,所以为了绑定关系,我们需要把本次创建的Observable所对应的observer传入到上次的Observable中,这个就叫作观察者上溯过程,所以才有Observable.this.subscribe(observerNext);这句代码,读者需要注意与.this.subscribe(observerNext)的区别,这个很重要。
这样子,我们就能够写出以下代码
Observable.create(new Observable<String>() {
@Override
public void subscribe(Observer<String> observer) {
observer.onNext("123");
observer.onComplete();
}
}).map(new Funtion<String, Integer>() {
@Override
public Integer transform(String s) {
return Integer.parseInt(s);
}
}).subscribe(new Observer<Integer>() {
@Override
public void onNext(Integer parms) {
}
@Override
public void onComplete() {
}
@Override
public void onError() {
}
});
}
至于线程切换操作,我们可以直接new一个Thread,再这里面进行异步处理(实际的RXJava有自己的实现,我们这里只是设计模式的模拟,简单处理多线程),那么放在什么时候比较合适呢,放在观察者上溯前面就比较合适了,即Observable中的subscribe方法被调用的时候。如下:
public Observable<T> subscribeOn() {
return new Observable<T>() {
@Override
public void subscribe(final Observer<T> observer) {
new Thread() {
@Override
public void run() {
super.run();
Observer<T> observerNext = new Observer<T>() {
@Override
public void onNext(T parms) {
Log.i("ObservableTest", "Observable in " + Thread.currentThread().getName());
observer.onNext(parms);
}
@Override
public void onComplete() {
observer.onComplete();
}
@Override
public void onError() {
observer.onError();
}
};
//将本次创建的Observe给上一轮的OObservable
Observable.this.subscribe(observerNext);
}
}.start();
}
};
代码是不是非常类似!那么切换回来主线程的时候呢?当然是在事件分发的时候调用啦,我们以onNext回调为例子,就有如下:
public Observable<T> observeOn() {
Handler handler=new Handler(Looper.getMainLooper());
return new Observable<T>() {
@Override
public void subscribe(final Observer<T> observer) {
Observer<T> observerNext = new Observer<T>() {
@Override
public void onNext(T parms) {
handler.post(new Runnable() {
@Override
public void run() {
Log.i("ObservableTest", "Observable in " + Thread.currentThread().getName());
observer.onNext(parms);
}
});
}
@Override
public void onComplete() {
observer.onComplete();
}
@Override
public void onError() {
observer.onError();
}
};
//将本次创建的Observe给上一轮的OObservable
Observable.this.subscribe(observerNext);
}
};
}
这里没有设定调度器,只是模拟RXJava设计,所以就有如下用法
Observable.create(new Observable<String>() {
@Override
public void subscribe(Observer<String> observer) {
Log.i("ObservableTest", "Observable subscribe in " + Thread.currentThread().getName());
observer.onNext("123");
observer.onComplete();
}
}).map(new Funtion<String, Integer>() {
@Override
public Integer transform(String s) {
return Integer.parseInt(s);
}
}).subscribeOn().observeOn().subscribe(new Observer<Integer>() {
@Override
public void onNext(Integer parms) {
Log.i("ObservableTest", "MainActivity in " + Thread.currentThread().getName());
Log.i("ObservableTest","MainActivity"+parms);
}
@Override
public void onComplete() {
}
@Override
public void onError() {
}
});
这样,一个完美的线程切换就完成啦!
总结
对于手写RXJava,需要各位看官们了解好之间的调用机制与对象机制,熟悉好RXJava的流程,再结合上述代码进行消化吸收噢!