2015-10-23 21 views
2

所以我有一個Track Id的列表,我需要執行一個網絡請求來獲取軌道詳細信息,我使用for循環來啓動所有請求和鎖等待所有請求完成。完成後,回調將與已填充的曲目列表一起發送。避免使用CountDownLatch在發送回調之前等待多個線程

我想知道是否有更好的方法來做到這一點,也許與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; 
} 

回答

1

如果你想使所有的請求異步和等待他們回來,你可以(爲簡潔和可讀性lambda表達式)這樣做:

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()) 
     ... 
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) { 

         } 
        }); 

編輯:您可以更改改造從web服務回報可觀,如果你這樣做,你將需要改變地圖以下

.flatMap(new Func1<Track, Observable<Response>>() { 
        @Override 
        public Observable<Response> call(Track track) { 
         return makeRequestThatReturnsObservable(track.id()); 
        } 
       }) 
相關問題