除了System.currentTimeMillis()之外,使用.defer()的一个很好的用例是什么?

时间:2018-04-11 11:07:39

标签: rx-java reactive-programming rx-java2

我有以下代码:

Single<Player> createPlayerSingle() {
    Integer playerId = Random.nextInteger();
    return playersDao.createSingle(id);
}

有人告诉我应该添加Single.defer()

Single<Player> createPlayerSingle() {
    return Single.defer(() -> {
        Integer playerId = Random.nextInteger();
        return playersDao.createSingle(id);
    }
}

我们的想法是,如果我们创建另一个createPlayerSingle()订阅,我们就不会生成新ID(基本上我们会重复使用旧ID)。

我无法理解为什么会这样。我们应该将defer添加到以某些同步代码块开头的每个函数吗?

Single<T> methodSingle() {
    return Single.defer(() -> {
        Integer id = Random.nextInteger(); // sync block of code
        ....
        return dao.createSingle(id);
    });
}

我确实理解defer做了什么(它为每个订阅者执行lambda,例如,如果我们将System.currentTimeMillis()放在lambda中,我们将收到2个不同的值,用于2个订阅,而不是1个相同的如果我们使用.just.fromCallable代替.defer),则会有价值。

当我们从参数中获取属性时,我们是否应该将defer放在这里?这对我来说没有意义(即使我们第二次订阅该方法的结果,我们会用一些参数调用它。)

Single<T> methodSingle(Object object) {
        return Single.defer(() -> {
            Integer id = object.id; // sync block of code
            ....
            return dao.createSingleFrom(id);
        });
    }

2 个答案:

答案 0 :(得分:0)

当您编写一个返回Single(或任何其他RxJava流类型)的方法时,您将返回可以多次订阅的内容,可能同时发送。

Defer是一个非常强大(但很简单)的运算符,允许您定义 per-subscription 状态。例如,如果您想要第一次发射的特殊行为:

Observable<Integer> numbers = Observable.just(1, 2, 3);
Observable<Integer> numbers2 = 
    Observable.defer(() -> {
        boolean[] first = new boolean[] {true};
        return numbers.doOnNext(x -> {
            if (first[0]) {
                System.out.println("first=" + x);
                first[0] = false;
            } else {
                System.out.println(x);
            }
        });
    });
numbers2.subscribe();
numbers2.subscribe();

产生

first=1
2
3
first=1
2
3

重新编码:

Single<T> methodSingle(Object object) {
    return Single.defer(() -> {
        Integer id = object.id; // sync block of code
        ....
        return dao.createSingleFrom(id);
    });
}

如果object是不可变的,那么这是毫无意义的,你可能会因为怀疑而遗漏defer

答案 1 :(得分:0)

每当我觉得需要使用.create()时,我意识到.defer()很简单。 .defer()准备代码通常是启动查询,并将结果推送到Observable.just()。