fromCallable() & defer() & andThen()

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,请勿转载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值