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);
});
}