所以我有一个Track Id列表,对于每个轨道我需要执行网络请求以获取轨道详细信息,我使用for循环来启动所有请求和一个锁存器等待所有请求到完成。完成后,回调将与已填充的曲目列表一起发送。
我想知道是否有更好的方法可以做到这一点,也许是使用RxJava?
我在Android中使用Retrofit 2.0。
public IBaseRequest batchTracksById(final TrackIdList trackIdListPayload, final IRequestListener<TracksList> listener) {
final TracksList tracks = new TracksList();
final Track[] trackArray = newrack[trackIdListPayload.getTrackIds().length];
tracks.setTrack(trackArray);
final CountDownLatch latch = new CountDownLatch(trackArray.length);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
latch.await();
handler.post(new Runnable() {
@Override
public void run() {
listener.onRequestUpdate(null, tracks, null, true);
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
for (String id : trackIdListPayload.getTrackIds()) {
getTrackById(id, new IRequestListener<Track>() {
@Override
public void onRequestFailure(IBaseRequest request, Exception exception) {
latch.countDown();
}
@Override
public void onRequestUpdate(IBaseRequest request, Track track, RequestState state, boolean requestComplete) {
//iterate through the tracks and update the ones in the thing
int i = 0;
for (String s : trackIdListPayload.getTrackIds()) {
if (s.equals(track.getTrackId())) {
trackArray[i] = track;
// don't break here, as we may have a case where we have multiple instances of the same trackId (although
// at the moment a request will be made for each anyway...
}
i++;
}
latch.countDown();
}
});
}
return null;
}
答案 0 :(得分:1)
如果我理解正确,您有一个轨道列表作为输入,您需要一个Web服务结果列表。如果您可以使网络调用同步(rxjava将为您处理后台处理),这是使用RxJava执行此操作的简单方法。
Observable.from(trackList)
.map(new Func1<Track, Response>() {
@Override
public Response call(Track track) {
return makeRequestSynchronously(track.id());
}
})
.toList()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<Response>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(List<Response> responses) {
}
});
编辑:您可以更改Retrofit以从webservice返回observable,如果您这样做,则需要将map更改为以下内容
.flatMap(new Func1<Track, Observable<Response>>() {
@Override
public Observable<Response> call(Track track) {
return makeRequestThatReturnsObservable(track.id());
}
})
答案 1 :(得分:1)
如果你想异步地发出所有请求并等待它们返回,你可以这样做(lambdas为了简洁和可读性):
tracks.flatMap(track -> getTrackDetails(track.id)
.subscribeOn(Schedulers.io()))
.toList()
.doOnNext(list -> processTrackList())
...
如果您要求以tracks
的顺序返回结果,但仍然是异步请求,那么很快就会发布rxjava 1.0.15,您将能够执行此操作
tracks.concatMapEager(track -> getTrackDetails(track.id)
.subscribeOn(Schedulers.io())
.toList()
.doOnNext(list -> processTrackList())
...