2017-02-08 17 views
5

Tôi đang sử dụng RxJava trong ứng dụng Android của mình cùng với Retrofit để thực hiện yêu cầu mạng cho máy chủ. Tôi đang sử dụng RxJavaCallAdapterFactory vì vậy tôi có thể có yêu cầu trang bị thêm của tôi trở về đĩa đơn. Trong mã của tôi, đối tượng trang bị thêm được đặt tên là 'api'.Chaining Singles cùng nhau trong RxJava

Mã ở đây hoạt động tốt, nhưng trong ví dụ này, tôi cần truy xuất userId trước khi tôi có thể tạo danh sách phát. Tôi căn bản ánh xạ yêu cầu userId tới yêu cầu API và sau khi tạo danh sách phát, tôi cần sử dụng lại bản đồ phẳng để chuyển đổi phản hồi JSON thành đối tượng có thể sử dụng.

public JSONUser me; 

public Single<String> getUserId(){ 

    if(me != null){ 
     return Single.just(me.getUserId()); 
    } 

    return api.getMe().flatMap(new Func1<JSONUser, Single<String>>() { 
     @Override 
     public Single<String> call(JSONUser meResult) { 
      me = meResult; 
      return Single.just(me.getUserId()); 
     } 
    }); 
} 

public Single<Playlist> createPlaylist(String name) { 

    final NewPlaylistConfig config = new NewPlaylistConfig(name); 

    return getUserId().flatMap(new Func1<String, Single<Playlist>>() { 
     @Override 
     public Single<Playlist> call(String userId) { 
      return api.createPlaylist(userId, config).flatMap(
        new Func1<JSONPlaylist, Single<? extends SpotifyPlaylist>>() { 
         @Override 
         public Single<? extends Playlist> call(JSONPlaylist data) { 
          return Single.just(new Playlist(data)); 
        } 
      }); 
     } 
    }); 
} 

Điểm vào ở đây sẽ là createPlaylist(). NewPlaylistConfig sẽ được chuyển thành JSON và chỉ đơn giản là tham số cơ thể cho yêu cầu POST. UserId là cần thiết như một tham số đường dẫn.

Câu hỏi chính của tôi ở đây, là nếu có cách để kết nối các hoạt động này mà không có "gọi lại-địa ngục" bạn thấy ở đây. Như tôi đã nói, mã này hoạt động nhưng nó thực sự xấu xí. Tôi sẽ đánh giá cao nếu ai đó có thể chỉ cho tôi đi đúng hướng về vấn đề này. Có cách nào để thực hiện công việc này như lời hứa nơi bạn có thể chỉ chuỗi.

Cảm ơn bạn.

+0

Liệu stackoverflow.com/questions/30269011/chain-two-retrofit-observables-w-rxjava trợ giúp này ? – Raghunandan

Trả lời

7

Thay vì:

getUserId() 
    .flatMap(new Func1<String, Single<Playlist>>() { 
     @Override 
     public Single<Playlist> call(String userId) { 
      return api.createPlaylist(userId, config).flatMap(
       new Func1<JSONPlaylist, Single<? extends SpotifyPlaylist>>() { 
        @Override 
        public Single<? extends Playlist> call(JSONPlaylist data) { 
         return Single.just(new Playlist(data)); 
        } 
      }); 
     } 
    }); 

viết:

getUserId() 
    .flatMap(new Func1<String, Single<Playlist>>() { 
     @Override 
     public Single<Playlist> call(String userId) { 
      return api.createPlaylist(userId, config); 
     } 
    }) 
    .flatMap(
     new Func1<JSONPlaylist, Single<? extends SpotifyPlaylist>>() { 
      @Override 
      public Single<? extends Playlist> call(JSONPlaylist data) { 
       return Single.just(new Playlist(data)); 
      } 
    }); 

Trên thực tế bạn có thể flatMap chuỗi (và bản đồ) như bạn chuỗi sau đó với những lời hứa.


Lưu ý bạn có thể thay thế các flatMap thứ hai với bản đồ, thay thế:

return Single.just(new Playlist(data)); 

với:

return new Playlist(data); 

Kết quả:

getUserId() 
    .flatMap(new Func1<String, Single<Playlist>>() { 
     @Override 
     public Single<Playlist> call(String userId) { 
      return api.createPlaylist(userId, config); 
     } 
    }) 
    .map(
     new Func1<JSONPlaylist, SpotifyPlaylist>() { 
      @Override 
      public SpotifyPlaylist call(JSONPlaylist data) { 
       return new Playlist(data); 
      } 
    }); 

.210

Edit: bạn có thể đi xa hơn với java 8:

getUserId() 
    .flatMap(userId -> api.createPlaylist(userId, config)) 
    .map(data -> new Playlist(data)); 

Hoặc Kotlin:

getUserId() 
    .flatMap { api.createPlaylist(it, config) } 
    .map { Playlist(it) } 
+0

Đây chính xác là những gì tôi cần, cảm ơn! – Jtvd78