所以我有一个可接收字符串的ConnectableObservable,对于每个字符串,我都需要执行查询(异步)并等待结果返回
此刻,我正在使用闩锁来等待查询返回,但是可以观察到的是它卡住了,或者只是结束了第一个字符串,而不继续其他字符串。
在此示例中我已经隔离了问题
private Subscriber<? super String> stringStreamInput;
ConnectableObservable<String> stringStream = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
stringStreamInput = subscriber;
}
})
.observeOn(Schedulers.io())
.map(new Func1<String, String>() {
@Override
public String call(String perro) {
return getPerroDetails(perro);
}
})
.publish();
stringStream.connect();
调用查询模拟的方法
private String getPerroDetails(final String perro) {
Log.d("Hey", "Perro " + perro);
//Simulating the query to get Perro details
String newPerro = executeQueryForPerro(perro);
Log.d("Hey", "NewPerro " + newPerro);
return newPerro;
}
使用CountDownLatch模拟查询
private String executeQueryForPerro(final String perro) {
final String[] newPerro = new String[1];
final CountDownLatch latch = new CountDownLatch(1);
//SIMULATION OF THE QUERY
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
newPerro[0] = perro + " reloaded ";
latch.countdown();
}
}, 1000);
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return newPerro[0];
}
测试
String[] perros = new String[]{"Beagle", "Alaska", "Chihuahua", "PitBull", "RedBull"};
for (String perro : perros) {
stringStreamInput.onNext(perro);
}
我还可以采取哪些其他方法来确保查询正确执行并等待结果返回到下一步?
有没有神奇的Rx解决方案?
非常感谢
答案 0 :(得分:1)
将RxJava与显式线程管理结合在一起时,通常会遇到问题,通常是在测试时。 RxJava工具包足够灵活,可以提供您几乎所需的一切。
数据源必须类似于Subject
。在您的代码中,您是直接向订户发送值,完全绕过了观察者链,这可能不是您想要的。
PublishSubject<String> stringStreamInput = PublishSubject.create();
然后,更改getPerroDetails()
以返回最终将提供结果的Observable
:
Observable<String> getPerroDetails(final String perro);
然后,您可以使用flatMap()
运算符获取详细信息:
Observable<String> stringStream = stringStreamInput
.observeOn(Schedulers.io())
.flatMap( input -> getPerroDetails(input) )
.publish();
stringStream.connect();
如何实施getPerroDetails()
?您可以使用RxJava运算符之一来调用异步方法:
Observable<String> getPerroDetails(String perro)
{
return Observable
.just( perro + " reloaded" )
.delay(1000, TimeUnit.MILLISECONDS));
}