我有以下代码:
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);
});
}
答案 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()。