RxJava是ReactiveX的Java实现,通过这个框架我们可以很方便的进行数据的异步获取,并对数据进行分步转换。
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.3'
首先创建一个观察者,它可以在数据发生改变的时候调用相应的回调函数。
Subscriber subscriber = new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
}
@Override
public void onNext(String s) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
};
//也可以用Observer创建观察者
Observer<String> observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
};
接下来创建被观察者,它需要一个ObservableOnSubscribe类型的参数。当Observable对象的subscribe方法被调用时,会调用到ObservableOnSubscribe里的subscribe回调方法,通过对emitter操作,开始向观察者发送事件。
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("发送第一个消息");
emitter.onNext("发送第二个消息");
emitter.onComplete();
}
});
//也可以这样写,这一行和上面的效果是一样的
Observable<String> observable2 = Observable.just("发送第一个消息","发送第二个消息");
当Observable的subscribe方法被调用时,会依次发送onNext,onNext,onComplete方法。
这里不保存变量了,直接在被观察者的订阅函数里新建并添加一个观察者。
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
emitter.onNext("发送第一个消息");
emitter.onNext("发送第二个消息");
emitter.onComplete();
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
System.out.println("我收到了:"+s);
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
@Override
public void onComplete() {
System.out.println("已接收全部事件");
}
});
被观察者中通过Emitter发送的事件都会按顺序被观察者接收并调用回调方法。
RxJava为我们提供了许多操作符,种类有创建操作符,变换操作符,过滤操作符,组合操作符,错误处理操作符,辅助操作符,条件和布尔操作符,算术聚合操作符,连接操作符等,以下将介绍一下常用的操作符。
1.interval
可以使用interval操作符起到定时器的作用,每隔一定时间发送一个事件。
Observable.interval(3, TimeUnit.SECONDS).subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
System.out.println(aLong+"");
}
});
2.range
range操作符可以发射有序的整数序列,代替for循环,第一个参数不小于0,第二个参数为终值,左闭右开。
Observable.range(0,5).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
}
});
3.repeat
可以把发送指定数据的过程重复N次。
Observable.range(0,3).repeat(2).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
}
});
这个调用会发送 0,1,2 两次,发送顺序为0,1,2,0,1,2。
1.map
map操作符可以将事件发送的数据映射成其他数据,例如给数据添加额外的信息,或获取它的某个字段,或包装等等。它的匿名内部类中声明的两个类型分别是处理前和处理后的数据类型。
Observable.just("人").map(new Function<String, String>() {
@Override
public String apply(String s) throws Exception {
return "好"+s;
}
});
事件的数据就从"人"变成了"好人"。
2.flatMap
这个操作符大概意思就是从发送数组事件展开成一个个单独的事件,具体没搞懂。
Observable.fromArray(1,2,3).flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
return Observable.just(integer+"已处理");
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println(s);
}
});
待续
1.filter
filter操作符可以过滤事件,只有通过的事件才能被之后的观察者收到。
Observable.just(1,2,3,4,5).filter(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) throws Exception {
return integer > 2;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("收到了"+integer);
}
});
这个例子中1,2事件都没有通过过滤器,只会输出收到3,4,5的消息。
2.elementAt
Observable.just(1,2,3,4).elementAt(2).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
}
});
返回指定位置的数据,这里accept函数只会收到3的事件。
3.distinct
这个操作符用来去重,当一个事件数据已经被发送过,则不会被再发送。
Observable.just(1,2,2,3,4,3,5).distinct().subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer+"");
}
});
去重之后的结果就是 1,2,3,4,5。
4.skip,take
skip操作符可以跳过前n个事件,take操作符只取前n个事件。
Observable.just(1,2,2,3,4,3,5).distinct().skip(2).take(2).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer+"");
}
});
这个例子首先去重,此时为1,2,3,4,5,再通过skip跳过前两个,变为3,4,5,再通过take取前两个,最终结果输出的是3,4。
操作符太多了,先忽略
如果不指定线程,Scheduler默认在调用subscribe方法的线程执行,我们可以通过调用subscribeOn或者ObserveOn方法传入Scheduler对象,影响操作执行的线程。
Scheduler的类型如下:
1. Schedulers.immediate():直接在当前线程执行
2. Schedulers.newThread():总是启用新线程执行
3. Schedulers.io():读写文件,数据库,网络交互等操作时采用,效率比newThread()高
4. Schedulers.computation():计算所使用的Scheduler,线程池为固定线程池,大小为cpu核数
5. Schedulers.trampoline():在当前线程入队,并不立即执行,按顺序执行队列中的任务
6. AndroidSchedulers.mainThread():RxAndroid库中提供的,在主线程中运行
直接分析下RxJava的源码,分为订阅,变换和线程切换三个部分。
从Observable的创建开始看起,首先看看create方法里做了什么。
public static <T> Observable<T> create(ObservableOnSubscribe<T> source) {
ObjectHelper.requireNonNull(source, "source is null");
return RxJavaPlugins.onAssembly(new ObservableCreate<T>(source));
}
这里会通过source对象创建一个ObservableCreate,我们来看下里面的内容。
public final class ObservableCreate<T> extends Observable<T> {
final ObservableOnSubscribe<T> source;
//构造函数里只是存储了source对象
public ObservableCreate(ObservableOnSubscribe<T> source) {
this.source = source;
}
@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);
}
}
...
}
可以看到它的构造函数里只是存储了source对象,接下来看看实际返回Observable对象的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;
}
可以看到,create方法创建后,会返回一个Observable对象,实际子类型是ObservableCreate。
开始监听时,会调用这个Observable对象的subscribe方法,看一下它的实际操作。
public final void subscribe(Observer<? super T> observer) {
ObjectHelper.requireNonNull(observer, "observer is null");
try {
//this是指Observable本身,observer是传进来的观察者,方法在后面
observer = RxJavaPlugins.onSubscribe(this, observer);
ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
//这里是调用子类Observable中定义的方法
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;
}
}
public static <T> Observer<? super T> onSubscribe(@NonNull Observable<T> source, @NonNull Observer<? super T> observer) {
BiFunction<? super Observable, ? super Observer, ? extends Observer> f = onObservableSubscribe;
if (f != null) {
return apply(f, source, observer);
}
//实际上还是返回的观察者本身
return observer;
}
这里调用到了subscribeActual方法,我们到ObservableCreate类中看一下。
@Override
protected void subscribeActual(Observer<? super T> observer) {
//这里首先创建一个CreateEmitter对象,它继承了ObservableEmitter和Disposable
CreateEmitter<T> parent = new CreateEmitter<T>(observer);
//调用观察者的回调函数,在事件发送之前被调用
observer.onSubscribe(parent);
try {
//这个方法是create的时候实现的,里面使用emitter对象发送具体的事件
source.subscribe(parent);
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
parent.onError(ex);
}
}
订阅过程就到这里了,接下来我们看看事件的发送过程。
emitter调用onNext方法来发送事件,还是用上边的例子,emitter的实际对象类型是CreateEmitter,它在ObservableCreate的subscribeActual里被创建。来看看onNext过程。
@Override
public void onNext(T t) {
if (t == null) {
onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
return;
}
if (!isDisposed()) {
//调用观察者的onNext方法
observer.onNext(t);
}
}
这里直接调用了observer的onNext方法,是我们在调用subscribe方法时传进来的内部类。这里看起来很简单,emitter的onNext方法的调用直接调用了观察者的调用,我们接下来看下数据的变换过程。
最常用的数据映射过程就是map操作符,我们看下它的内容。
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));
}
和create方法里的结构看起来差不多,其实逻辑也是一样的,这里返回的时候会返回一个ObservableMap类型的对象。
当调用完map之后再调用subscribe方法,里面调用到的方法就是ObservableMap里面的subscribeActual方法,我们看下它的内容。
@Override
public void subscribeActual(Observer<? super U> t) {
source.subscribe(new MapObserver<T, U>(t, function));
}
里面就一行,source是ObservableMap创建时传进来的上一个Observable对象,也就是ObservableCreate对象,这里调用它的subscribe方法,传入一个包装的MapObserver对象。
接下来的流程和之前一样,直到emitter.onNext方法会调用:
@Override
public void onNext(T t) {
if (t == null) {
onError(new NullPointerException("onNext called with null. Null values are generally not allowed in 2.x operators and sources."));
return;
}
if (!isDisposed()) {
//之前的observer是我们subscribe时候创建的,但此时这个observer对象是包装了一层的MapObserver对象,所以会调用到它里面的onNext方法
observer.onNext(t);
}
}
让我们看一下MapObserver类中的onNext方法做了些什么。
@Override
public void onNext(T t) {
if (done) {
return;
}
if (sourceMode != NONE) {
actual.onNext(null);
return;
}
//map转换之后的对象
U v;
try {
//进行转换的过程
v = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper function returned a null value.");
} catch (Throwable ex) {
fail(ex);
return;
}
actual.onNext(v);
}
其中actual对象是被包装的Observer,mapper为自定义的转换方法。在onNext方法里面会调用我们自定义的转换方法进行数据类型转换,然后调用被包装observer的onNext。
可以看出,map通过Observer的包装,来处理了事件数据的转换过程,然后再调用被包装的observer时,传递过去的就是已经转换过的数据了。
还有一个比较重要的是线程切换的过程,先上示例代码。
Observable.just(1).subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.d("prozac",Thread.currentThread().getName());
}
});
在一个普通的事件订阅流程中间添加了subscribeOn(Schedulers.newThread()),让我们看下它做了些什么。
//格式和其他的操作符一样,直接到subscribe过程调用到ObservableSubscribeOn的subscribeActual方法
public final Observable<T> subscribeOn(Scheduler scheduler) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}
@Override
public void subscribeActual(final Observer<? super T> observer) {
//包装了一层Observer
final SubscribeOnObserver<T> parent = new SubscribeOnObserver<T>(observer);
observer.onSubscribe(parent);
//可以看到此处并没有像其他操作符一样继续调用subscribe,我们看看这里的调用具体做了什么
parent.setDisposable(scheduler.scheduleDirect(new SubscribeTask(parent)));
}
首先看看创建出来的SubscribeTask对象是什么。
final class SubscribeTask implements Runnable {
private final SubscribeOnObserver<T> parent;
SubscribeTask(SubscribeOnObserver<T> parent) {
this.parent = parent;
}
@Override
public void run() {
//SubscribeTask是内部类,外部类的属性可以直接访问到
source.subscribe(parent);
}
}
可以看到这个Task继承了Runnable,是交给线程执行的,执行的时候,还是调用了source.subscribe方法。
在分析scheduler.scheduleDirect方法之前,我们先看看我们在外部通过Schedulers.newThread()创建的scheduler对象是什么。
public static Scheduler newThread() {
return RxJavaPlugins.onNewThreadScheduler(NEW_THREAD);
}
@NonNull
static final Scheduler NEW_THREAD;
static {
NEW_THREAD = RxJavaPlugins.initNewThreadScheduler(new NewThreadTask());
}
static final class NewThreadTask implements Callable<Scheduler> {
@Override
public Scheduler call() throws Exception {
return NewThreadHolder.DEFAULT;
}
}
static final class NewThreadHolder {
static final Scheduler DEFAULT = new NewThreadScheduler();
}
public final class NewThreadScheduler extends Scheduler {
final ThreadFactory threadFactory;
private static final String THREAD_NAME_PREFIX = "RxNewThreadScheduler";
private static final RxThreadFactory THREAD_FACTORY;
/** The name of the system property for setting the thread priority for this Scheduler. */
private static final String KEY_NEWTHREAD_PRIORITY = "rx2.newthread-priority";
static {
int priority = Math.max(Thread.MIN_PRIORITY, Math.min(Thread.MAX_PRIORITY,
Integer.getInteger(KEY_NEWTHREAD_PRIORITY, Thread.NORM_PRIORITY)));
THREAD_FACTORY = new RxThreadFactory(THREAD_NAME_PREFIX, priority);
}
public NewThreadScheduler() {
this(THREAD_FACTORY);
}
public NewThreadScheduler(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
}
@NonNull
@Override
public Worker createWorker() {
return new NewThreadWorker(threadFactory);
}
}
兜兜转转一大堆类,可以看到实际创建出来的Scheduler是一个NewThreadScheduler类型的对象。接下来看看scheduleDirect操作。
public Disposable scheduleDirect(@NonNull Runnable run) {
return scheduleDirect(run, 0L, TimeUnit.NANOSECONDS);
}
public Disposable scheduleDirect(@NonNull Runnable run, long delay, @NonNull TimeUnit unit) {
//在NewThreadScheduler类中被重写,在下面附上代码
final Worker w = createWorker();
final Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
DisposeTask task = new DisposeTask(decoratedRun, w);
//通过Worker对象调用schedule方法,也在下面附上代码
w.schedule(task, delay, unit);
return task;
}
//NewThreadScheduler中的方法
Override
public Worker createWorker() {
return new NewThreadWorker(threadFactory);
}
//NewThreadWorker中的方法
public NewThreadWorker(ThreadFactory threadFactory) {
executor = SchedulerPoolFactory.create(threadFactory);
}
//这里可以看到创建了我们熟悉的线程池
public static ScheduledExecutorService create(ThreadFactory factory) {
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1, factory);
tryPutIntoPool(PURGE_ENABLED, exec);
return exec;
}
@NonNull
@Override
public Disposable schedule(@NonNull final Runnable run) {
return schedule(run, 0, null);
}
@NonNull
@Override
public Disposable schedule(@NonNull final Runnable action, long delayTime, @NonNull TimeUnit unit) {
if (disposed) {
return EmptyDisposable.INSTANCE;
}
return scheduleActual(action, delayTime, unit, null);
}
//实际通过线程池执行Task的方法
public ScheduledRunnable scheduleActual(final Runnable run, long delayTime, @NonNull TimeUnit unit, @Nullable DisposableContainer parent) {
Runnable decoratedRun = RxJavaPlugins.onSchedule(run);
//将Runnable包装为ScheduledRunnable
ScheduledRunnable sr = new ScheduledRunnable(decoratedRun, parent);
if (parent != null) {
if (!parent.add(sr)) {
return sr;
}
}
Future<?> f;
try {
//根据延迟实际将ScheduledRunnable使用线程池执行
if (delayTime <= 0) {
f = executor.submit((Callable<Object>)sr);
} else {
f = executor.schedule((Callable<Object>)sr, delayTime, unit);
}
sr.setFuture(f);
} catch (RejectedExecutionException ex) {
if (parent != null) {
parent.remove(sr);
}
RxJavaPlugins.onError(ex);
}
return sr;
}
SubscribeOn的大致流程为:
1.我们调用subscribeOn方法时传入一个Schedule的子类对象。
2.在订阅过程中subscribeActual被调用时会将下一次调用subscribe的操作放在一个Runnable里。
3.然后通过Schedule创建一个Worker,这个Worker对象里维护了一个线程池,将传进来的Runnable通过线程池进行调用。
4.Observable的subscribe方法在目标线程中被调用,上游发送事件的操作就会在目标线程中执行,这就起到了切换上游执行线程的目的。
接下来看看ObserveOn做了些啥。
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> observeOn(Scheduler scheduler) {
return observeOn(scheduler, false, bufferSize());
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.CUSTOM)
public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
ObjectHelper.requireNonNull(scheduler, "scheduler is null");
ObjectHelper.verifyPositive(bufferSize, "bufferSize");
return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
}
public final class ObservableObserveOn<T> extends AbstractObservableWithUpstream<T, T> {
final Scheduler scheduler;
final boolean delayError;
final int bufferSize;
public ObservableObserveOn(ObservableSource<T> source, Scheduler scheduler, boolean delayError, int bufferSize) {
super(source);
this.scheduler = scheduler;
this.delayError = delayError;
this.bufferSize = bufferSize;
}
//直接从订阅时的这个方法开始看
@Override
protected void subscribeActual(Observer<? super T> observer) {
//TrampolineScheduler表明执行在当前线程,不做线程切换直接调用subscribe
if (scheduler instanceof TrampolineScheduler) {
source.subscribe(observer);
} else {
//创建了特定Worker
Scheduler.Worker w = scheduler.createWorker();
//包裹一层ObserveOnObserver并调用subscribe
source.subscribe(new ObserveOnObserver<T>(observer, w, delayError, bufferSize));
}
}
...
}
可以看到在subscribe时,ObservableObserveOn的subscribeActual方法里还是照常调用subscribe的,只是设置了非TrampolineScheduler的时候观察者外包了一层ObserveOnObserver。
订阅完成之后就等emitter的onNext调用了,我们直接看看当ObserveOnObserver的onNext方法被调用的时候做了什么操作。
@Override
public void onNext(T t) {
if (done) {
return;
}
//这里不知道干啥的,希望看到的朋友们指点一下
if (sourceMode != QueueDisposable.ASYNC) {
queue.offer(t);
}
schedule();
}
void schedule() {
if (getAndIncrement() == 0) {
//可以看到此时worker去执行this,自身继承了Runnable接口,看看run方法内容
worker.schedule(this);
}
}
@Override
public void run() {
//这个标志好像是异步和同步分别调用
if (outputFused) {
drainFused();
} else {
//我们主要看异步情况下调用的这个方法
drainNormal();
}
}
void drainNormal() {
int missed = 1;
final SimpleQueue<T> q = queue;
final Observer<? super T> a = downstream;
for (;;) {
if (checkTerminated(done, q.isEmpty(), a)) {
return;
}
for (;;) {
boolean d = done;
T v;
try {
v = q.poll();
} catch (Throwable ex) {
Exceptions.throwIfFatal(ex);
disposed = true;
upstream.dispose();
q.clear();
a.onError(ex);
worker.dispose();
return;
}
boolean empty = v == null;
if (checkTerminated(d, empty, a)) {
return;
}
if (empty) {
break;
}
//a为下游对象,在这里会调用到下游的onNext。
a.onNext(v);
}
missed = addAndGet(-missed);
if (missed == 0) {
break;
}
}
}
ObserveOn实现流程是这样的:
1.订阅时判断设置的Scheduler是否需要切换线程,如果是就包一层Observer。
2.在事件传递时,调用schedule方法,将自身放入Worker中执行。
3.自身的run方法在目标线程中执行,调用drainNormal方法,进行一系列判断之后调用了下游的onNext方法,起到了下游线程切换的效果。
关于RxJava就分析到这里了,只是粗略看下,里面还有很多细节没有分析,感兴趣的同学可以自己深究一下,如果有写的不对的地方欢迎大家指正。