defer() 是一个创建操作符,它会一直等待直到有观察者订阅它,才使用Observable工厂方法生成一个Observable,并且为每个观察者创建一个新的Obserable。
正题
先来看个例子:
public class SomeType {
private String value;
public void setValue(String value) {
this.value = value;
}
public Observable<String> valueObservable() {
return Observable.just(value);
}
public static void main(String[] args) {
SomeType some = new SomeType();
Observable<String> observable = some.valueObservable();
some.setValue("小龙虾");
observable.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("s == " + s);
}
});
}
}
在上面的代码中,我先创建了Observable
,然后再给SomeType
对象赋值,最后订阅一个观察者来获取SomeType
对象的value
。可能我们所期望的是打印出小龙虾
三个字,然而却直接抛了个空指针出来。
just()
、fromXXX()
,以及其他的Observable
创建方法都是在创建的时候存储数据,而不是在被订阅的时候。在这个例子中,我所期望的是无论何时请求valueObservable()
方法,都能返回单前的value
。
当你处于此种尴尬场景的时候,可能你会这么做:
public Observable<String> valueObservable() {
return Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext(value);
e.onComplete();
}
});
}
这样做,确实达到了订阅的时候才创建Observable
。
defer()
操作符便是把细节封装了起来,让使用更加方便,更加简单:
public Observable<String> valueObservable(){
return Observable.defer(new Callable<ObservableSource<? extends String>>() {
@Override
public ObservableSource<? extends String> call() throws Exception {
return Observable.just(value);
}
});
}
深入
当你想在一个方法中将数据写入disk,并且返回此数据,可以通过defer()
来实现:
public Observable<SomeType> createSomeType(String value) {
return Observable.defer(() -> {
SomeType someType = new SomeType();
someType.setValue(value);
try {
db.writeToDisk(someType);
}
catch (IOException e) {
return Observable.error(e);
}
return Observable.just(someType);
});
}