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