RxJava学习 - 4. Other Observable sources

Observable.range()

可以使用Observable.range()发射一定范围内的整数。从start值开始发送发射,每次加1,直到一定的count。这些数通过onNext()事件传递,跟着一个onComplete()事件:

import io.reactivex.Observable;

public class Launcher {
    public static void main(String[] args) {
        Observable.range(1,10)
            .subscribe(s -> System.out.println("RECEIVED: " + s));
    }
}

可以使用Observable.rangeLong()发射比较大的数。

Observable.interval()

Observable.interval()生成一个基于时间的Observable。每经过一个时间间隔它将发射一个连续的long emission(从0开始)。
下面的代码,每秒钟发射一个数:

import io.reactivex.Observable;
import java.util.concurrent.TimeUnit;

public class Launcher {
    public static void main(String[]args) {
        Observable.interval(1, TimeUnit.SECONDS)
            .subscribe(s -> System.out.println(s + " Mississippi"));
        sleep(5000);
    }
    
    public static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Observable.interval()在一个定时器上运行,所以,需要一个单独的线程做调度。上面的程序,main()方法生成一个Observable,但是不等它完成。它在一个新的线程上发射。要让main()不退出,我们使用sleep()方法让程序存活了5秒钟。在程序退出之前,我们的Observable有5秒钟时间可以发射。当你增加一个生产程序的时候,你一般不会碰到这样的问题,web服务、Android程序或者JavaFX将保持程序的存活。
Observable.interval()返回的是一个hot还是cold Observable?因为它是事件驱动的(页数无限的),你可能会说它是hot。
但是,增加一个Observer,等5秒钟,再加一个Observer。发生了什么?请看:

import io.reactivex.Observable;
import java.util.concurrent.TimeUnit;

public class Launcher {
    public static void main(String[] args) {
        Observable<Long> seconds = Observable.interval(1, TimeUnit.SECONDS);
        //Observer 1
        seconds.subscribe(l -> System.out.println("Observer 1: " + l));
        //sleep 5 seconds
        sleep(5000);
        //Observer 2
        seconds.subscribe(l -> System.out.println("Observer 2: " + l));
        //sleep 5 seconds
        sleep(5000);        
    }

    public static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出是这样的:

Observer 1: 0
Observer 1: 1
Observer 1: 2
Observer 1: 3
Observer 1: 4
Observer 1: 5
Observer 2: 0
Observer 1: 6
Observer 2: 1
Observer 1: 7
Observer 2: 2
Observer 1: 8
Observer 2: 3
Observer 1: 9
Observer 2: 4

5秒钟过去了,Observer 2来了。注意,它有自己的计时器,从0开始。这两个observers实际上有他们自己的emissions,每个都是从0开始。
所以,这个Observable实际上是cold。想让所有的observers使用同一个计时器,可以使用ConnectableObservable:

import io.reactivex.Observable;
import java.util.concurrent.TimeUnit;

public class Launcher {
    public static void main(String[] args) {
        ConnectableObservable<Long> seconds =
                Observable.interval(1, TimeUnit.SECONDS).publish();
        //observer 1
        seconds.subscribe(l -> System.out.println("Observer 1: " + l));
        seconds.connect();
        //sleep 5 seconds
        sleep(5000);
        //observer 2
        seconds.subscribe(l -> System.out.println("Observer 2: " + l));
        //sleep 5 seconds
        sleep(5000);
    }

    public static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出如下:

Observer 1: 0
Observer 1: 1
Observer 1: 2
Observer 1: 3
Observer 1: 4
Observer 1: 5
Observer 2: 5
Observer 1: 6
Observer 2: 6
Observer 1: 7
Observer 2: 7
Observer 1: 8
Observer 2: 8
Observer 1: 9
Observer 2: 9

Observable.future()

RxJava的Observables比Futures更健壮和富有表现力,但是,如果你现在使用的库仍然生产Futures,可以很容易地把他们转换成Observables:

import io.reactivex.Observable;
import java.util.concurrent.Future;

public class Launcher {
    public static void main(String[] args) {
    Future<String> futureValue = ...;
    Observable.fromFuture(futureValue)
        .map(String::length)
        .subscribe(System.out::println);
    }
}

Observable.empty()

看上去好像没什么用,但是,Observable可以什么都不发射,然后调用onComplete():

import io.reactivex.Observable;

public class Launcher {
    public static void main(String[] args) {
    Observable<String> empty = Observable.empty();
    
    empty.subscribe(System.out::println,
        Throwable::printStackTrace,
        () -> System.out.println("Done!"));
    }
}

空的observables通常代表空的数据集。有时候,有些运算也能返回空,比如filter()。有时候,你故意使用Observable.empty()。
empty Observable实质上就是RxJava的null。Empty Observables比null优雅,程序会继续,不会抛NullPointerExceptions。

Observable.never()

Observable.empty()的近亲是Observable.never()。唯一的不同是,它不调用onComplete(),observers一直在等emissions,却永远等不来:

import io.reactivex.Observable;

public class Launcher {
    public static void main(String[] args) {
        Observable<String> empty = Observable.never();
        empty.subscribe(System.out::println,
                Throwable::printStackTrace,
                () -> System.out.println("Done!"));
        sleep(5000);
    }
}

这个Observable主要用来测试,生产中不经常使用。我们使用sleep(),就像Observable.interval()那样,因为main线程产生Observable以后不会等待。
这个例子里,我们等了5秒钟,就是为了证明什么都没发射,然后,程序退出。

Observable.error()

你可以增加一个Observable,立刻调用onError():

import io.reactivex.Observable;

public class Launcher {
    public static void main(String[] args) {
        Observable.error(new Exception("Crash and burn!"))
                .subscribe(i -> System.out.println("RECEIVED: " + i),
                        Throwable::printStackTrace,
                        () -> System.out.println("Done!"));
    }
}

你也可以使用lambda提供异常,这样给每个Observer提供了单独的异常实例:

import io.reactivex.Observable;

public class Launcher {
    public static void main(String[] args) {
        Observable.error(() -> new Exception("Crash and burn!"))
                .subscribe(i -> System.out.println("RECEIVED: " + i),
                        Throwable::printStackTrace,
                        () -> System.out.println("Done!"));
    }
}

Observable.defer()

Observable.defer()是一个强有力的工厂,为每个Observer增加单独的状态。当使用一定的Observable工厂的时候,如果你的源是有状态的,你可能想给每个Observer增加单独的状态。你的源Observable可能不知道它的参数已经修改了,发送过时的emissions。这里有个简单的例子,你有一个Observable.range(),有两个静态的int属性:start和count。
如果你订阅这个Observable,修改count,然后再次订阅,你会发现,第二个Observer没看到这个变化:

import io.reactivex.Observable;

public class Launcher {
    private static int start = 1;
    private static int count = 5;
    
    public static void main(String[] args) {
        Observable<Integer> source = Observable.range(start, count);
        source.subscribe(i -> System.out.println("Observer 1: " + i));
        //modify count
        count = 10;
        source.subscribe(i -> System.out.println("Observer 2: " + i));
    }
}

输出是这样的:

Observer 1: 1
Observer 1: 2
Observer 1: 3
Observer 1: 4
Observer 1: 5
Observer 2: 1
Observer 2: 2
Observer 2: 3
Observer 2: 4
Observer 2: 5

想解决这个问题,你能玩儿每个订阅者增加一个fresh Observable。使用Observable.defer()就可以实现,它接受一个lambda,
说明怎么为每个订阅者增加一个Observable。因为这样做每次增加一个新的Observable,就可以反映参数的变化:

import io.reactivex.Observable;

public class Launcher {
    private static int start = 1;
    private static int count = 5;
    
    public static void main(String[] args) {
        Observable<Integer> source = Observable.defer(() ->
                Observable.range(start,count));
        source.subscribe(i -> System.out.println("Observer 1: " + i));
        //modify count
        count = 10;
        source.subscribe(i -> System.out.println("Observer 2: " + i));
    }
}

输出是这样的:

Observer 1: 1
Observer 1: 2
Observer 1: 3
Observer 1: 4
Observer 1: 5
Observer 2: 1
Observer 2: 2
Observer 2: 3
Observer 2: 4
Observer 2: 5
Observer 2: 6
Observer 2: 7
Observer 2: 8
Observer 2: 9
Observer 2: 10

如果你的Observable源是原生实现,而且超过一个Observer(比如,重新使用一个Iterator,该迭代器只迭代一次),也可以使用Observable.defer()解决。

Observable.fromCallable()

如果你需要执行一个计算或者动作,然后发射它,你可以使用Observable.just()(或者Single.just()、Maybe.just())。
但是,有时候,我们想晚一点再做,或者是deferred的方式。而且,如果处理过程发生错误,我们希望以onError()的方式发到Observable chain,而不是以Java传统的方式抛异常。例如,如果你的Observable.just()想用1除以0,会抛异常,但是不发给Observer:

import io.reactivex.Observable;

public class Launcher {
    public static void main(String[] args) {
    Observable.just(1 / 0)
            .subscribe(i -> System.out.println("RECEIVED: " + i),
                    e -> System.out.println("Error Captured: " + e));
    }
}

输出是:

java.lang.ArithmeticException: / by zero

	at Launcher.main(Launcher.java:6)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)

如果希望响应式地处理错误,把错误发给Observer处理。上面的例子,可以使用Observable.fromCallable(),它接受一个lambda Supplier,发生错误时会发射给Observer:

import io.reactivex.Observable;

public class Launcher {
    public static void main(String[] args) {
        Observable.fromCallable(() -> 1 / 0)
            .subscribe(i -> System.out.println("Received: " + i),
                e -> System.out.println("Error Captured: " + e));
    }
}

输出是:

Error Captured: java.lang.ArithmeticException: / by zero

猜你喜欢

转载自blog.csdn.net/weixin_43364172/article/details/84030755