10.从架构设计角度分析AAC源码-Rxjava2源码解析第4篇:责任链模式理解Rxjava2(包含背压和操作符)

48 阅读9分钟

前言

Rxjava2从使用者角度来说,可以从观察者订阅被观察者理解,被观察者可以进行类型转换,即操作符运算,被观察者和观察者可以在指定线程上操作,即异步

Rxjava2的核心是异步和操作符(数据流)运算

从源码角度来说,个人感觉从责任链模式角度理解当前Rxjava2架构比观察者模式更加合适。

demo

Flowable.create(new FlowableOnSubscribe<String>() {
        @Override
        public void subscribe(@NonNull FlowableEmitter<String> emitter) throws Exception {

            emitter.onNext("1");
            emitter.onNext("2");
            emitter.onNext("3");
            emitter.onComplete();
        }
    }, BackpressureStrategy.ERROR)
                    .map(new Function<String, String>() {

                        @Override
                        public String apply(@androidx.annotation.NonNull String s) throws Exception {
                            return "中间做了转换:" + s;
                        }
                    })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<String>() {
                @Override
                public void onSubscribe(Subscription s) {
					//一次性接受数据的最大个数,当前数据如果不设置,那么将不会接受到数据
                    s.request(3);
                }

                @Override
                public void onNext(String user) {
                    Timber.d("tag:" + user);
                }

                @Override
                public void onError(Throwable t) {
                    Timber.d("tag错误:" + t);
                }

                @Override
                public void onComplete() {
                    Timber.d("tag完成:");
                }
            });

简单解读

  1. 使用发射器发射数据:

     emitter.onNext("1");
     emitter.onNext("2");
     emitter.onNext("3");
     emitter.onComplete();
    
  2. 使用一个转换器将数据做了加工(操作符):

     new Function<String, String>() {
    
         @Override
         public String apply(@androidx.annotation.NonNull String s) throws Exception {
             return "中间做了转换:" + s;
         }
     }
    
  3. 发射数据加工过的新数据(如果没有第二步,这里表示发射的数据)指定执行线程:

     .subscribeOn(Schedulers.io())
    
  4. 指定接收数据线程:

     .observeOn(AndroidSchedulers.mainThread())
    
  5. 接收数据:

     new Subscriber<String>() {
         @Override
         public void onSubscribe(Subscription s) {
             s.request(3);
         }
    
         @Override
         public void onNext(String user) {
             Timber.d("tag:" + user);
         }
    
         @Override
         public void onError(Throwable t) {
             Timber.d("tag错误:" + t);
         }
    
         @Override
         public void onComplete() {
             Timber.d("tag完成:");
         }
     }
    

Rxjava2从责任链模式理解架构

架构设计

  1. 定义一个发射器接口,用于发射数据、发射完成、发射异常处理;

  2. 定义一个被订阅者接口,当前接口订阅一个发射器:该发射器用于发射数据;

  3. 定义一个订阅者接口,接受被订阅者或者上一个订阅者传递过来的数据;

  4. 定义一个基类处理器(下面所有处理器都继承当前处理器);

  5. 定义一个处理器,当前处理器用于①创建发射器,②创建的发射器交给被订阅者(用于发射数据、发射完毕、发射异常处理);③将传递过来的下游订阅者作为参数传递给发射器,发射器发射数据/发射完毕/发射异常的同时通知下游订阅者;

  6. 定义一个处理器,用于指定线程处理上游订阅者;

  7. 定义一个处理器,指定线程处理下游订阅者;

代码实现

  1. 定义一个发射器接口,用于发射数据、发射完成、发射异常处理;

     public interface Emitter<T> {
     
         void onNext(@NonNull T value);
     
         void onError(@NonNull Throwable error);
     
         void onComplete();
     }
    
  2. 定义一个被订阅者接口,当前接口订阅一个发射器:该发射器用于发射数据;

     public interface FlowableOnSubscribe<T> {
     
         void subscribe(@NonNull FlowableEmitter<T> emitter) throws Exception;
     }
    
  3. 定义一个订阅者接口,接受被订阅者或者上一个订阅者传递过来的数据;

     public interface Subscriber<T> {
         //该方法用于传递当前对象(作为上游对象)传递给下游处理器,
         public void onSubscribe(Subscription s);
     
         public void onNext(T t);
     
         public void onError(Throwable t);
     
         public void onComplete();
     }
    
  4. 定义一个基类处理器(下面所有处理器都继承当前处理器);

     public abstract class Flowable<T> implements Publisher<T> {
     	
     	//定义一个创建发射器的处理器
         public static <T> Flowable<T> create(FlowableOnSubscribe<T> source, BackpressureStrategy mode) {
             ObjectHelper.requireNonNull(source, "source is null");
             ObjectHelper.requireNonNull(mode, "mode is null");
             return new FlowableCreate<T>(source, mode);
         }
    
     	//数据流转换-后面会讲到
     	public final <R> Flowable<R> map(Function<? super T, ? extends R> mapper) {
             ObjectHelper.requireNonNull(mapper, "mapper is null");
             return new FlowableMap<T, R>(this, mapper);
         }
     
     	//上游的数据在指定线程上执行
         public final Flowable<T> subscribeOn(@NonNull Scheduler scheduler, boolean requestOn) {
             ObjectHelper.requireNonNull(scheduler, "scheduler is null");
             return new FlowableSubscribeOn<T>(this, scheduler, requestOn);
         }
     
     	//下游订阅者对象在指定线程上执行:指定方法,因为某些方法不需要在指定线程处理。
         public final Flowable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
             ObjectHelper.requireNonNull(scheduler, "scheduler is null");
             ObjectHelper.verifyPositive(bufferSize, "bufferSize");
             return new FlowableObserveOn<T>(this, scheduler, delayError, bufferSize);
         }
     
     	//解决背压问题-后面会讲到
     	@Override
         public final void subscribe(Subscriber<? super T> s) {
            
             ObjectHelper.requireNonNull(s, "s is null");
             subscribeActual(new StrictSubscriber<T>(s));
             
         }
     	//将下游对象传递给当前处理器
     	protected abstract void subscribeActual(Subscriber<? super T> s);
     }
    
  5. 定义一个处理器,当前处理器用于①创建发射器,②创建的发射器交给被订阅者(用于发射数据、发射完毕、发射异常处理);③将传递过来的下游订阅者作为参数传递给发射器,发射器发射数据/发射完毕/发射异常的同时通知下游订阅者;

     public final class FlowableCreate<T> extends Flowable<T> {
     
         final FlowableOnSubscribe<T> source;
     
         public FlowableCreate(FlowableOnSubscribe<T> source) {
             this.source = source;
         }
     
         @Override
         public void subscribeActual(Subscriber<? super T> t) {
     		//1.创建发射器,并且将下游订阅者对象传递给发射器,发射器方法调用时传递给下游订阅者方法
             BaseEmitter<T> emitter = new BaseEmitter<T>(t);
     		
     		//2.当前发射器作为上游对象传递给下游订阅者
             t.onSubscribe(emitter);
             try {
     			//发射器对象传递给并订阅者,被订阅者使用当前发射器发射数据
                 source.subscribe(emitter);
             } catch (Throwable ex) {
                 Exceptions.throwIfFatal(ex);
                 emitter.onError(ex);
             }
     		
     		static class BaseEmitter<T>
                 extends AtomicLong
                 implements FlowableEmitter<T>, Subscription {
     			private static final long serialVersionUID = 7326289992464377023L;
     
     			final Subscriber<? super T> downstream;
     
     			final SequentialDisposable serial;
     
     			BaseEmitter(Subscriber<? super T> downstream) {
     				this.downstream = downstream;
     				this.serial = new SequentialDisposable();
     			}
     			
     		}
     		
     		@Override
     		onNext(T t){
     			downstream.onNext(t)
     		}
     		
     		@Override
             public void onComplete() {
                 downstream.onComplete()
     		}
     		
     		@Override
     		public void onError(){
     			downstream.onError();
     		}
         }
     }
    
  6. 定义一个处理器,用于指定线程处理上游订阅者:以下代码相对来说比较简单,我就直接全部贴出来了,

     public final class FlowableSubscribeOn<T> extends Flowable<T> {
     
         /**
          * The upstream source Publisher.
          */
         protected final Flowable<T> source;
     
         final Scheduler scheduler;
     
         final boolean nonScheduledRequests;
     
         public FlowableSubscribeOn(Flowable<T> source, Scheduler scheduler, boolean nonScheduledRequests) {
             super(source);
             this.scheduler = scheduler;
             this.source = source;
             this.nonScheduledRequests = nonScheduledRequests;
         }
     
         @Override
         public void subscribeActual(final Subscriber<? super T> s) {
             Scheduler.Worker w = scheduler.createWorker();
     		//创建一个订阅者对象,将上一个处理器传递(上游订阅者)的对象作为参数
             final SubscribeOnSubscriber<T> sos = new SubscribeOnSubscriber<T>(s, w, source, nonScheduledRequests);
     		
     		//将当前SubscribeOnSubscriber对象作为上游订阅者传递给下一个处理器
             s.onSubscribe(sos);
     
     		//其实就是执行SubscribeOnSubscriber的run方法,表示指定线程处理SubscribeOnSubscriber
             w.schedule(sos);
         }
     
         static final class SubscribeOnSubscriber<T> extends AtomicReference<Thread>
         implements FlowableSubscriber<T>, Subscription, Runnable {
     
             private static final long serialVersionUID = 8094547886072529208L;
     
             final Subscriber<? super T> downstream;
     
             final Scheduler.Worker worker;
     
             final AtomicReference<Subscription> upstream;
     
             final AtomicLong requested;
     
             final boolean nonScheduledRequests;
     
             Publisher<T> source;
     
             SubscribeOnSubscriber(Subscriber<? super T> actual, Scheduler.Worker worker, Publisher<T> source, boolean requestOn) {
                 this.downstream = actual;
                 this.worker = worker;
                 this.source = source;
                 this.upstream = new AtomicReference<Subscription>();
                 this.requested = new AtomicLong();
                 this.nonScheduledRequests = !requestOn;
             }
     
             @Override
             public void run() {
                 lazySet(Thread.currentThread());
                 Publisher<T> src = source;
                 source = null;
                 src.subscribe(this);
             }
     
             @Override
             public void onSubscribe(Subscription s) {
                 if (SubscriptionHelper.setOnce(this.upstream, s)) {
                     long r = requested.getAndSet(0L);
                     if (r != 0L) {
                         requestUpstream(r, s);
                     }
                 }
             }
     
             @Override
             public void onNext(T t) {
                 downstream.onNext(t);
             }
     
             @Override
             public void onError(Throwable t) {
                 downstream.onError(t);
                 worker.dispose();
             }
     
             @Override
             public void onComplete() {
                 downstream.onComplete();
                 worker.dispose();
             }
     
             @Override
             public void request(final long n) {
                 if (SubscriptionHelper.validate(n)) {
                     Subscription s = this.upstream.get();
                     if (s != null) {
                         requestUpstream(n, s);
                     } else {
                         BackpressureHelper.add(requested, n);
                         s = this.upstream.get();
                         if (s != null) {
                             long r = requested.getAndSet(0L);
                             if (r != 0L) {
                                 requestUpstream(r, s);
                             }
                         }
                     }
                 }
             }
     
             void requestUpstream(final long n, final Subscription s) {
                 if (nonScheduledRequests || Thread.currentThread() == get()) {
                     s.request(n);
                 } else {
                     worker.schedule(new Request(s, n));
                 }
             }
     
             @Override
             public void cancel() {
                 SubscriptionHelper.cancel(upstream);
                 worker.dispose();
             }
     
             static final class Request implements Runnable {
                 final Subscription upstream;
                 final long n;
     
                 Request(Subscription s, long n) {
                     this.upstream = s;
                     this.n = n;
                 }
     
                 @Override
                 public void run() {
                     upstream.request(n);
                 }
             }
         }
     }
    
  7. 定义一个处理器,指定线程处理下游订阅者:当前处理器处理下游订阅者,指定线程处理指定方法-onNext、onComplete、onError;

     public final class FlowableObserveOn<T> extends AbstractFlowableWithUpstream<T, T> {
         final Scheduler scheduler;
     
         final boolean delayError;
     
         final int prefetch;
     
         public FlowableObserveOn(
                 Flowable<T> source,
                 Scheduler scheduler,
                 boolean delayError,
                 int prefetch) {
             super(source);
             this.scheduler = scheduler;
             this.delayError = delayError;
             this.prefetch = prefetch;
         }
     
         @Override
         public void subscribeActual(Subscriber<? super T> s) {
             Worker worker = scheduler.createWorker();
     		
     		//因为下游订阅者不是全部方法都在指定线程上处理,所以把工作线程worker作为参数传递给当前对象,目的是执行我们需要在指定线程上处理的方法
     		//当前订阅者对象作为下游对象,传递给上一个处理器,目的是上一个处理器的订阅者执行onNext接受(onComplete,onError)数据方法时传递到当前订阅者对象中
             source.subscribe(new ObserveOnSubscriber<T>(s, worker, delayError, prefetch));
             
         }
     	
     	...
     }
    

扩展

操作符-数据流

在这里插入图片描述

上图所示Rxjava2支持的所有操作符。我们这里仅仅对map(最简单的一个)进行监督解析,情看FlowableMap类,核心方法如下:

在这里插入图片描述

解决背压问题

1.什么是背压

背压是一种现象,简单来说就是在异步操作中,上游发送数据速度快于下游处理数据的速度,下游来不及处理,Buffer 溢出,导致事件阻塞,从而引起的各种问题,比如事件丢失,OOM等。

在rxjava1中并不支持背压,当出现事件阻塞时候,会直接抛出 MissingBackpressureException 异常,但是在rxjava2中,提供了 Flowable 来创建被观察者,通过Flowable 来处理背压问题,我们可以简单通过demo分析。

在这里插入图片描述

A:我们上游模拟循环发送数据。

B:线程切换,异步操作。

C:下游每隔一秒获取数据。

我们Observable 创建,来模拟了背压这个现象,我们在上游模拟无限循环的发送数据,下游每次都休眠一秒再获取数据,这样肯定会造成我们前面提的问题,就是上游发送太他丫的快了,下游根本处理不过来,我们先看结果。

在这里插入图片描述

看日志,打印结果停留在了13就没有继续打印了?同时可以看到程序已经崩了,是因为在rxjava2中,Observable并不支持背压操作,遇到背压问题,它并不会报错,也不会抛MissingBackpressureException 异常,但是内存会一直飙高,最后导致内存不足程序直接挂掉。

2.如何解决背压问题

我们设置两个参数,一个参数用来确定发射器发送数据的最大个数,一个参数用来确定订阅者一次性接受数据最大个数,并且如果订阅者没有设置一次性接受数据最大个数,那么当前发射器数据始终存在于缓存中。

  1. 通过Subscription对象的request方法设置被订阅者的最大接受数据(默认设置128)和订阅者一次性接受最大数据(必须用户手动设置);

  2. FlowableObserveOn类中有一个runAsync方法,该方法有一个轮询,直到订阅者设置了一次性最大接受数据才会开始接受数据

在这里插入图片描述

五种观察者模式

在这里插入图片描述

参考

Rxjava2(二)、五种观察者模式创建及背压

总结

以上包括前面的文章,好坏参半,也表现了作者当前水平。Rxjava2目前来说解说完毕,后面可能还会对当前的知识重新理解。

每一次认真阅读源码都有不一样的收获。

当前源码标签使用AAC-Rxjava2篇