我有以下代码:
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);
});
}
当你编写一个返回Single
(或任何其他 RxJava 流类型(的方法时,你返回的东西可以多次订阅,可能同时订阅。
Defer
是一个非常强大(但简单(的运算符,允许您定义每个订阅的状态。例如,如果您希望第一次排放具有特殊行为:
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
。
每次我觉得有必要弄乱 .create(( 时,我意识到使用 .defer(( 很简单。.defer(( prep 代码通常是启动查询并将结果推入 Observable.just(( 的代码。