RxJava2.X源码分析(六):变换操作符的实现原理强化篇(下)

一 前言

Ok,我们在上一篇RxJava2.X 源码分析(五):变换操作符的实现原理(上)中分析了RxJava2中转换操作符map的实现过程
本次我们将紧跟上篇的步伐,分析比map更为强大的flatMap操作符的实现流程

二 Demo

首先,我们还是老样子,先看一个demo:

  Observable observable = Observable.create(new ObservableOnSubscribe() {
    
    
      @Override
    public void subscribe(@NonNull ObservableEmitter emitter) throws Exception {
    
    
          emitter.onNext(1);
          emitter.onNext(2);
          emitter.onNext(3);

      }

  });

  observable.flatMap(new Function>() {
    
    
      @Override
    public ObservableSource apply(@NonNull Integer integer) throws Exception {
    
    

          return Observable.just(integer*integer);
      }
  }).subscribe(new Consumer() {
    
    
      @Override
    public void accept(@NonNull Integer integer) throws Exception {
    
    
          Log.i(TAG, ">>>data is : " + integer);
      }
  });
============================================================================
2021-02-04 09:32:06.714 14161-14161/com.example.myapplication D/flatMap:: 1
2021-02-04 09:32:06.714 14161-14161/com.example.myapplication D/flatMap:: 4
2021-02-04 09:32:06.714 14161-14161/com.example.myapplication D/flatMap:: 9

我们重点来看一下applay方法返回的类型,显然易见,Map()方法直接返回的是事件类型,如Integer类型,而flatMap()方法则是返回一个Observable类型;那么这个区别能提供怎样的能力呢? 1、比如连续两个串行的网络请求 2、如数据类型的中间转换等等,
也就是说,我们能以很自然流畅的方式在中间做一些转换,能做的事情很多哦。
我们开始进入正题,看下内部是如何实现的呢?从flatMap方法进去。

 @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper) {
    
    
        return flatMap(mapper, false);
    }


    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper, boolean delayErrors) {
    
    
        return flatMap(mapper, delayErrors, Integer.MAX_VALUE);
    }


    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper, boolean delayErrors, int maxConcurrency) {
    
    
        return flatMap(mapper, delayErrors, maxConcurrency, bufferSize());
    }


    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final <R> Observable<R> flatMap(Function<? super T, ? extends ObservableSource<? extends R>> mapper,
            boolean delayErrors, int maxConcurrency, int bufferSize) {
    
    
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
        ObjectHelper.verifyPositive(bufferSize, "bufferSize");
        if (this instanceof ScalarCallable) {
    
    
            @SuppressWarnings("unchecked")
            T v = ((ScalarCallable<T>)this).call();
            if (v == null) {
    
    
                return empty();
            }
            return ObservableScalarXMap.scalarXMap(v, mapper);
        }
        return RxJavaPlugins.onAssembly(new ObservableFlatMap<T, R>(this, mapper, delayErrors, maxConcurrency, bufferSize));
    }

这里经过重复的调用flatMap()方法,将一些参数传入进去:

  1. delayErrors:是否延迟错误处理
  2. maxConcurrency:最大的并发量
  3. bufferSize:队列的大小

Ok,最终调用了含有四个参数的flatMap()方法,我们重点看一下这个方法:

  public final <R> Observable<R> flatMap(Functionsuper T, ? extends ObservableSourceextends R>> mapper,
          boolean delayErrors, int maxConcurrency, int bufferSize) {
    
    
          //1、做一些值的判断,不符合规定我就报一场
      ObjectHelper.requireNonNull(mapper, "mapper is null");
      ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
      ObjectHelper.verifyPositive(bufferSize, "bufferSize");
      //2、判断我们的上游Obsevable是否是ScalarCallable类型,做特殊处理,我们的上游如果是Observable.just就会走这里(just方法返回的Observable是实现了ScalarCallable接口的)
      if (this instanceof ScalarCallable) {
    
    
          @SuppressWarnings("unchecked")
          T v = ((ScalarCallable<T>)this).call();
          if (v == null) {
    
    
              return empty();
          }
          return ObservableScalarXMap.scalarXMap(v, mapper);
      }
      //3、OK,看到我们熟悉的方法了
      return RxJavaPlugins.onAssembly(new ObservableFlatMap<T, R>(this, mapper, delayErrors, maxConcurrency, bufferSize));

在这里我们先来看一下Observable.just()这个方法:

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public static <T> Observable<T> just(T item) {
    
    
    ObjectHelper.requireNonNull(item, "The item is null");
    return RxJavaPlugins.onAssembly(new ObservableJust<T>(item));
}






public final class ObservableJust<T> extends Observable<T> implements ScalarCallable<T> {
    
    

    private final T value;
    public ObservableJust(final T value) {
    
    
        this.value = value;
    }

    @Override
    protected void subscribeActual(Observer<? super T> s) {
    
    
        ScalarDisposable<T> sd = new ScalarDisposable<T>(s, value);
        s.onSubscribe(sd);
        sd.run();
    }

    @Override
    public T call() {
    
    
        return value;
    }
}

这里的流程相信大家很熟悉了,就是对上游的Observable进行包装之后被下游的订阅后触发subscribeActual()方法,我们主要来看看这里的方法:

@Override
protected void subscribeActual(Observer<? super T> s) {
    
    
    ScalarDisposable<T> sd = new ScalarDisposable<T>(s, value);
    s.onSubscribe(sd);
    sd.run();
}

这里对传入的Observer进行了包装,我们来看看ScalarDisposable这个类:

public final class ObservableScalarXMap {
    
    
......
 public static final class ScalarDisposable<T>
    extends AtomicInteger
    implements QueueDisposable<T>, Runnable{
    
    

        @Override
        public void run() {
    
    
            if (get() == START && compareAndSet(START, ON_NEXT)) {
    
    
                observer.onNext(value);
                if (get() == ON_NEXT) {
    
    
                    lazySet(ON_COMPLETE);
                    observer.onComplete();
                }
            }

}
.......
}

ScalarDisposable是ObservableScalarXMap(之后会详细说一下这个类) 这个类的内部类,而且它实现了Runable接口,重写了run()方法;在这里调用了Observer里的方法实现事件的接收;事实上这里也的确在ObservableJust被订阅时调用了(subscribeActua()方法里)。

Ok,分析完Observabvle.just()方法,我们思路回过来,继续看flatMap()里的实现就简单多了:

 public final <R> Observable<R> flatMap(Functionsuper T, ? extends ObservableSourceextends R>> mapper,
          boolean delayErrors, int maxConcurrency, int bufferSize) {
    
    
          //1、做一些值的判断,不符合规定我就报一场
      ObjectHelper.requireNonNull(mapper, "mapper is null");
      ObjectHelper.verifyPositive(maxConcurrency, "maxConcurrency");
      ObjectHelper.verifyPositive(bufferSize, "bufferSize");
      //2、判断我们的上游Obsevable是否是ScalarCallable类型,做特殊处理,我们的上游如果是Observable.just就会走这里
      if (this instanceof ScalarCallable) {
    
    
          @SuppressWarnings("unchecked")
          T v = ((ScalarCallable<T>)this).call();
          if (v == null) {
    
    
              return empty();
          }
          return ObservableScalarXMap.scalarXMap(v, mapper);
      }
      //3、OK,看到我们熟悉的方法了
      return RxJavaPlugins.onAssembly(new ObservableFlatMap<T, R>(this, mapper, delayErrors, maxConcurrency, bufferSize));

这里分两种情况:

  1. 第一种:ObservableScalarXMap.scalarXMap(v, mapper)
    当上游Obsevable是ScalarCallable类型,就会走这里,上面分析过,Observable.just返回的就是ScalarCallable类型的Observable

  2. 第二种: return RxJavaPlugins.onAssembly(new ObservableFlatMap<T, R>(this, mapper, delayErrors, maxConcurrency, bufferSize));
    我们的demo就是属于第二种情况。

我们先来看第一种情况:ObservableScalarXMap.scalarXMap(v, mapper),首先对两个参数要有所理解,v其实就是just()方法里面出入的值,mapper就是我们new出来的function类了。OK,前面在讲just()方法原理的时候出现过了ObservableScalarXMap类,just()方法里利用ObservableScalarXMap类里的Observer包装类对下游Observer类进行包装,接收上游Observable下发的数据,不懂流程的小伙伴可以倒回去看看just()的执行过程。
我们来看看ObservableScalarXMap的scalarXMap()方法:

  public static <T, U> Observable<U> scalarXMap(T value,
            Function<? super T, ? extends ObservableSource<? extends U>> mapper) {
    
    
            //对上有Observerable进行包装
        return RxJavaPlugins.onAssembly(new ScalarXMapObservable<T, U>(value, mapper));
    }

 static final class ScalarXMapObservable<T, R> extends Observable<R> {
    
    

        final T value;

        final Function<? super T, ? extends ObservableSource<? extends R>> mapper;

        ScalarXMapObservable(T value,
                Function<? super T, ? extends ObservableSource<? extends R>> mapper) {
    
    
            this.value = value;
            this.mapper = mapper;
        }

        @SuppressWarnings("unchecked")
        @Override
        public void subscribeActual(Observer<? super R> s) {
    
    
            ObservableSource<? extends R> other;
            try {
    
    
            //获取applay方法里的返回值(Observable)
                other = ObjectHelper.requireNonNull(mapper.apply(value), "The mapper returned a null ObservableSource");
            } catch (Throwable e) {
    
    
                EmptyDisposable.error(e, s);
                return;
            }
            if (other instanceof Callable) {
    
    
                R u;

                try {
    
    
                    u = ((Callable<R>)other).call();
                } catch (Throwable ex) {
    
    
                    Exceptions.throwIfFatal(ex);
                    EmptyDisposable.error(ex, s);
                    return;
                }

                if (u == null) {
    
    
                    EmptyDisposable.complete(s);
                    return;
                }
                //这个类很熟悉吧,没错就是just()方法原理的出现过的,这里ScalarDisposable实现了Runnable接口,在run方法里下游Observer会对上有Observable下发的数据进行接收。
                ScalarDisposable<R> sd = new ScalarDisposable<R>(s, u);
                s.onSubscribe(sd);
                sd.run();
            } else {
    
    
            
                other.subscribe(s);
            }
        }
    }

其实很简单,这里也分两种情况:

  1. 第一种,如果applay方法返回的是实现了Callable接口的,就会按照just()方法的原理流程走
  2. 第二种,如果不是,就直接执行subscribe()方法按照正常的流程走。

Ok,现在我们来根据Demo里的方法走,flatMap()返回
return RxJavaPlugins.onAssembly(new ObservableFlatMap<T, R>(this, mapper, delayErrors, maxConcurrency, bufferSize));
我们先来看看ObservableFlatMap这个类:

public final class ObservableFlatMap<T, U> extends AbstractObservableWithUpstream<T, U> {
    
    }

可以看到,ObservableFlatMap的包装以之前的线程实现类型,同样是继承了AbstractObservableWithUpstream类,也就是说,内部有source存储我们上游的Observable
构造方法比较简单,主要就是赋值:

  public ObservableFlatMap(ObservableSource<T> source,
          Functionsuper T, ? extends ObservableSourceextends U>> mapper,
          boolean delayErrors, int maxConcurrency, int bufferSize) {
    
    
      super(source);
      this.mapper = mapper;
      this.delayErrors = delayErrors;
      this.maxConcurrency = maxConcurrency;
      this.bufferSize = bufferSize;
  }

Ok,我们看重点subscribeActual方法,其触发是在下游Observer调用subscribe订阅时

  @Override
  public void subscribeActual(Observer<? super U> t) {
    
    
      //1、同样是对Scalar的处理
      if (ObservableScalarXMap.tryScalarXMapSubscribe(source, t, mapper)) {
    
    
          return;
      }
      //2、重点在这里,t为下游的Observer,mapper为我们的funcation,T为接收类型,R为转换后类型

      source.subscribe(new MergeObserver<T, U>(t, mapper, delayErrors, maxConcurrency, bufferSize));
  
}

看2处代码:source为上游Observable,也就是我们这里new了一个中间Obsever来订阅上游Observable,然后中间Observer接收到上游下发的数据,猜测还是调用来mapper.apply获得转换后的Obsevable类型,然后还是看代码吧:
static final class MergeObserver<T, U> extends AtomicInteger implements Disposable, Observer {

     ...
      MergeObserver(Observersuper U> actual, Functionsuper T, ? extends ObservableSourceextends U>> mapper,
              boolean delayErrors, int maxConcurrency, int bufferSize) {
    
    
          //1、下游的Observer,用于后面数据的传递
          this.actual = actual;
          //2、funcation,用于转换函数的操作
          this.mapper = mapper;
          this.delayErrors = delayErrors;
          //3、并发数,因为中间我们转换后的Obsevable可能接收一个值然后产生多个值,如调用Observable.fromArray(),
          this.maxConcurrency = maxConcurrency;
          this.bufferSize = bufferSize;
          //4、存储apply返回的Observable
          if (maxConcurrency != Integer.MAX_VALUE) {
    
    
              sources = new ArrayDeque<? extends U>>(maxConcurrency);
          }
          this.observers = new AtomicReference[]>(EMPTY);
      }
  }

OK,看完了构造方法,我们看下MergeObserver的onSubscribe以及onXXX(),执行完source.subscribe(new MergeObserver<T, U>(t, mapper, delayErrors, maxConcurrency, bufferSize));后,我们的onSubscribe会被调用,然后就是onXXX();

  public void onSubscribe(Disposable s) {
    
    
      if (DisposableHelper.validate(this.s, s)) {
    
    
          this.s = s;
          actual.onSubscribe(this);
      }
  }

在onSubscribe中只是简单的调用actual.onSubscribe(this)进行事件的传递,同时存储Disposable进行Disposable事件的管理。

OK,那么重点应该在onNext(T t):

@Override
  public void onNext(T t) {
    
    
      // safeguard against misbehaving sources
    if (done) {
    
    
          return;
      }
      ObservableSource<? extends U> p;
      try {
    
    
          //1、调用mapper.apply获得转换函数的返回值Observable。
          p = ObjectHelper.requireNonNull(mapper.apply(t), "The mapper returned a null ObservableSource");
      } catch (Throwable e) {
    
    
      //2、发生异常时终止
          Exceptions.throwIfFatal(e);
          s.dispose();
          onError(e);
          return;
      }
    //3、如果你明确设置了maxConcurrency,需要入队列进行排队处理,因为要控制并发量
      if (maxConcurrency != Integer.MAX_VALUE) {
    
    
          synchronized (this) {
    
    
              if (wip == maxConcurrency) {
    
    
                  sources.offer(p);
                  return;
              }
              wip++;
          }
      }
    //4、内部订阅处理,因为返回的p是observable,所以内部肯定还需要通过下游的Observer订阅它,这样数据流才能继续下发。
      subscribeInner(p);
  }

OK,那么我们继续分析subscribeInner,看内部如何订阅

 void subscribeInner(ObservableSourceextends U> p) {
    
    
      for (;;) {
    
    
          if (p instanceof Callable) {
    
    
              tryEmitScalar(((Callableextends U>)p));

              if (maxConcurrency != Integer.MAX_VALUE) {
    
    
                  synchronized (this) {
    
    
                      p = sources.poll();
                      if (p == null) {
    
    
                          wip--;
                          break;
                      }
                  }
              } else {
    
    
                  break;
              }
          } else {
    
    
          //1、this及为我们的MergeObserver对象,再次wrapper,
              InnerObserver<T, U> inner = new InnerObserver<T, U>(this, uniqueId++);
              if (addInner(inner)) {
    
    
                    //触发订阅,如此,我们下游的Observer就开始等着接收数据流了。  
                    p.subscribe(inner);                 
              }
              break;
          }
      }
  }

OK,基本上整个flatMap的转换流程也就分析完了,其余太细的点,我们就不继续深入,因为本次我们的目的就是了解其实现流程即可。在宏观上进行把控。

三 总结

Ok,根据上面的分析,其实对于flatMap的操作过程我们已经很清楚了,其跟map基本一样,通过在中间使用装饰者模式插入一个中间的Observable和Observe,你可以想象为代理。
代理Observable做的事就是接收下游Obsever的订阅事件,然后通过代理Obsever订阅上游Observer,然后在上游Observer下发数据給代理Observer时,通过先调用mapper.apply转换回调函数获得转换后的Observable,内部通过下游Observer再次订阅,然后转换后返回的Observable下发数据给下游Obsever。
OK,通过从第一篇到本篇,我们不难发现,基本都是一样的模式,通过装饰者模式中间产生一个Observable和Observer,完成订阅事件的传递以及下发数据流的传递,进过我们中间产生的Observable和Observer时,根据具体需求做一些操作。
理解了这些,相信你再去看其他操作符的代码时,按这个思路去看,基本都是Ok的。
希望通过本篇的学习,大家对于RxJava2的内部实现的一些流程更为熟悉。

猜你喜欢

转载自blog.csdn.net/qq_39431405/article/details/113624403