rxJava的使用--Observable的创建及源码分析(二)

6, from,
从create得知,如果我们的消息源有多个时,我们要多次调用onNext,Subscriber才能全部收到所有信息,而通过from来创建,我们则不需要自己调用onNext,rxjava会自动为我们调用了.
代码如下:

  String[] values = new String[]{"1", "2", "3"};
        Observable.from(values).subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                System.out.println("---- onCompleted ----");
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("---- onError ----");
            }

            @Override
            public void onNext(String s) {
                System.out.println("---- onNext ----" + s);
            }
        });

运行结果如下:

---- onNext ----1
---- onNext ----2
---- onNext ----3
---- onCompleted ----

从这里看我们并没有调用onNext,onCompleted.但是我们却可以收到对应的信息,from为我们做了什么呢?
源码分析如下:

    public static <T> Observable<T> from(T[] array) {
        // 这里判断我们传入的数组是否为空
        int n = array.length;
        // 如果为空则调用empty创建Observable,这里可以参考之前分析的empty方法
        if (n == 0) {
            return empty();
        } else
        // 这里just方法下面再讲
        if (n == 1) {
            return just(array[0]);
        }
        // 如果传入的数组的长度>1的时候这调用该方法
        return create(new OnSubscribeFromArray<T>(array));
    }

去看一下OnSubscribeFromArray内部:

public final class OnSubscribeFromArray<T> implements OnSubscribe<T> {
    final T[] array;
    public OnSubscribeFromArray(T[] array) {
       // 这里可以知道该类会保存一份我们传入的数组元素
        this.array = array;
    }
    ... 忽略部分
    }

接着我们看到该类的call方法:

@Override
    public void call(Subscriber<? super T> child) {
        child.setProducer(new FromArrayProducer<T(child, array));
    }

这里我们先看child.setProducer方法做了什么:

    public void setProducer(Producer p) {
        ... 忽略部分
        // 从这里可以看出该方法是一个递归调用
        if (passToSubscriber) {
            subscriber.setProducer(producer);
        } else {
        // 我们目前只需要看到这一部分就可以了
        // 从这里看到这个调用的是Producer 里面的request方法
            if (toRequest == NOT_SET) {
                producer.request(Long.MAX_VALUE);
            } else {
                producer.request(toRequest);
            }
        }
    }

从源码可以看出该方法里面调用了FromArrayProducer里面的request方法,好了我们现在去看一下该方法做了什么.

  @Override
        public void request(long n) {
            ... 忽略部分
            // 这里判断根据出传入的n来判断是调用fastPath,还是slowPath.
            // 经过我的几次调试该方法都是调用fastPath的
            if (n == Long.MAX_VALUE) {
                if (BackpressureUtils.getAndAddRequest(this, n) == 0) {
                    fastPath();
                }
            } else
            if (n != 0) {
                if (BackpressureUtils.getAndAddRequest(this, n) == 0) {
                    slowPath(n);
                }
            }
        }

通过几次调试发现该方法都是调用fastPath的,该方法的源码如下:

 void fastPath() {
            final Subscriber<? super T> child = this.child;

            for (T t : array) {
                if (child.isUnsubscribed()) {
                    return;
                }

                child.onNext(t);
            }

            if (child.isUnsubscribed()) {
                return;
            }
            child.onCompleted();
        }

看到该方法应该就很清楚from做了什么吧.它内部已经循环帮我调用onNext方法了,并在最后调用onCompleted.跟运行结果一致.

7,interval
该方法演示的时候有点麻烦,我用的junit来测试的,代码如下:

       Observable.interval(1, TimeUnit.SECONDS)
                .subscribe(new Subscriber<Long>() {
                    @Override
                    public void onCompleted() {
                        System.out.println("---- onCompleted ----");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("---- onError ----");
                    }

                    @Override
                    public void onNext(Long aLong) {
                        System.out.println("---- onNext ----" + aLong);
                    }
                });


        Thread.sleep(10000);

运行结果如下:

---- onNext ----0
---- onNext ----1
---- onNext ----2
---- onNext ----3
---- onNext ----4
---- onNext ----5
---- onNext ----6
...

interval是每隔我们指定的时间就调用一次,因为我是用过junit运行的,如果线程不阻塞,还没等到Observable输出程序就退出了.
源码分析如下:

  public static Observable<Long> interval(long interval, TimeUnit unit) {
  // 在这里涉及到调度器,因为我们还没讲到该内容,在这里我们只需要知道
  // interval的运行不是在本线程调用即可
        return interval(interval, interval, unit, Schedulers.computation());
    }

从上面的源码知道interval是通过调度器来运行的Schedulers.computation(),这也是我们阻塞了线程,程序还能输出的原因了.
继续看interval内部的源码:

 public static Observable<Long> interval(long initialDelay, long period, TimeUnit unit, Scheduler scheduler) {
       return create(new OnSubscribeTimerPeriodically(initialDelay,period,unit,scheduler));
    }

看到OnSubscribeTimerPeriodically类里面的call方法:

    @Override
    public void call(final Subscriber<? super Long> child) {
        final Worker worker = scheduler.createWorker();
        child.add(worker);
        worker.schedulePeriodically(new Action0() {
            long counter;
            @Override
            public void call() {
                try {
                // 看到这里每次都调用onNext
                    child.onNext(counter++);
                } catch (Throwable e) {
                // 如果有异常就取消订阅
                    try {
                        worker.unsubscribe();
                    } finally {
                        Exceptions.throwOrReport(e, child);
                    }
                }
            }
            // 这里可以看到,该方法是定时调用的
        }, initialDelay, period, unit);
    }

通过该方法就很清楚,为什么interval为什么能一直输出了.这里涉及到调度器的内容,我们先不讲,只需要知道,它会在子线程里面调用onNext方法.这样也看到call的方法内,没有调用onCompleted也就是说,该方法除非去掉订阅,否则不会结束.

8,Just
代码如下:

Observable.just("1","2","3")
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        System.out.println("---- onCompleted ----" );
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("---- onError ----");
                    }

                    @Override
                    public void onNext(String s) {
                        System.out.println("---- onNext ----" + s);
                    }
                });

运行结果如下:

---- onNext ----1
---- onNext ----2
---- onNext ----3
---- onCompleted ----

just的用法和from的用法类似,区别的是,just传入多个参数,而from是直接传入数组的.在分析from源码的时候知道,如果传入from数组的长度为1的时候调用的just来创建的.
源码分析:

   public static <T> Observable<T> just(T t1, T t2, T t3) {
        return from((T[])new Object[] { t1, t2, t3 });
    }

从这里看到just传入多个参数的时候调用的还是from来创建的.
下面需要分析的just传入一个参数的时候:

public static <T> Observable<T> just(final T value) {
        return ScalarSynchronousObservable.create(value);
    }

得知底部是通过调用ScalarSynchronousObservable方法里面的call来调用的:

  protected ScalarSynchronousObservable(final T t) {
        super(new OnSubscribe<T>() {

            @Override
            public void call(Subscriber<? super T> s) {
                // setProducer已经在分析from的时候分析过了,这里就不再分析了
                s.setProducer(createProducer(s, t));
            }

        });
        this.t = t;
    }

底部是通过setProducer来调用的前面已经分析过该方法了这里就不再分析了.

接着看下面一段代码:

    String value = "1";
        Observable<String> observable = Observable.just(value);

        value = "1000";

        observable.subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                System.out.println("---- onCompleted ----" );
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("---- onError ----" );
            }

            @Override
            public void onNext(String s) {
                System.out.println("---- onNext ----" + s);
            }
        });

输出结果是1还是1000呢?可能很多人以为是1000,但是输出结果却是这样的:

---- onNext ----1
---- onCompleted ----

为什么会这样呢?我们知道just一个参数的时候调用的是ScalarSynchronousObservable的call方法,看一下该类做什么:

  protected ScalarSynchronousObservable(final T t) {
        ... 忽略部分
        // 这里,保存了我们在just传进来的值,这也是为什么输出的一个旧的值
        this.t = t;
    }

遇到这种问题应该怎么解决呢? 在这里我们只想存在订阅者也就是调用subscribe方法是输出value 方式的值.大家还记得前面介绍defer方法吗?该方法就是在调用subscribe方法时才真正去创建Observable的实例,因此我们的代码可以这样写:

   String finalValue = "1";
    @Test
    public void testDefer3(){
        Observable observable = Observable.defer(new Func0<Observable<String>>() {
            @Override
            public Observable call() {
                return Observable.just(finalValue);
            }
        });
        finalValue = "1000";
        observable.subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                System.out.println("---- onCompleted ----");
            }

            @Override
            public void onError(Throwable e) {
                System.out.println("---- onError ----");

            }

            @Override
            public void onNext(String o) {
                System.out.println("---- onNext ----" + o);
            }
        }); 
    }

这时候大家应该知道输出结果是什么了吧.
输出结果:

---- onNext ----1000
---- onCompleted ----

从上面也可以知道just会在内部保存创建的值,如果改值是普通类型,不是对象引用的时候,则会出现输出旧值的情况.通过defer就可以很好的解决该问题了.

你可能感兴趣的:(java,rxjava)