1. fromCallable() & defer() 介绍
fromCallable() 和 defer()都是可以延迟执行直到有订阅者订阅。
不同点是defer()是无状态的,针对每次订阅,即如果我们放 System.currentTimeMillis() 到 lambda表达式中,我们将得到两个不同的值。 如果有两次订阅,使用.fromCallable 或者 .just ,那么将只有一个相同的值。
2. andThen()
Completable.andThen() 被用作连续执行, 但是andThen()中的lambda表达式也有执行时机的不同。
(1)例:
class User {
String name;
}
private User mUser; // this is a global variable
public Observable<String> stringObservable() {
return Completable.fromAction(() -> {
mUser = new User();
mUser.name = "name";
}).andThen(Observable.just(mUser.name));
}
首先,我在Completable.fromAction中做了一些初始化,我希望andThen运算符只在完成Completable.fromAction后启动.
这意味着我希望在andThen运算符启动时初始化mUser.
订阅后得到如下错误:
问题出在使用Observable.just(mUser.name)语句. just运算符将尝试立即创建observable,虽然它只会在Completable.fromAction之后发出.于是使用just创建Observable时,mUser为null.
应该使用如下代码替代:
andThen(Observable.defer(() -> Observable.just(mUser.name)));
andThen(Observable.fromCallable(() -> mUser.name));
(2)真实问题:
问题代码:
return Single.fromCallable(() -> newBalanceRegister)
.flatMap(register -> populateOperationNumbers(model, register)
.andThen(Single.fromCallable(() -> {
final Optional<Long> maxRegisterOperationNumber = register.getOperations()
.stream()
.map(BalanceRegisterOperation::getNumber)
.max(Long::compareTo);
if (maxRegisterOperationNumber.isPresent() && shouldUpdateRegisterNumber(register,
maxRegisterOperationNumber.get())) {
register.setNumber(maxRegisterOperationNumber.get());
}
return register;
})))
.flatMap(
register -> sourceToDistributeService.applySources(register).andThen(proceedWithBBREvents(register)));
问题出在最后一行:proceedWithBBREvents会立即创建Single导致了event 没有发送, 因为 allocation 还没有完成。
解决方案
return populateOperationNumbers(model, newBalanceRegister)
.andThen(Completable.defer(() -> {
final Optional<Long> maxRegisterOperationNumber = newBalanceRegister.getOperations()
.stream()
.map(BalanceRegisterOperation::getNumber)
.max(Long::compareTo);
if (maxRegisterOperationNumber.isPresent() && shouldUpdateRegisterNumber(newBalanceRegister,
maxRegisterOperationNumber.get())) {
newBalanceRegister.setNumber(maxRegisterOperationNumber.get());
}
return sourceToDistributeService.applySources(newBalanceRegister);
}))
.andThen(Completable.defer(() -> proceedWithBBREvents(newBalanceRegister)))
.andThen(Single.fromCallable(() -> newBalanceRegister));
修正了RxJava的使用方法和顺序,现在可以正确的订阅事件了。
该笔记取自同事Zijie,请勿转载。