2016-04-22 19 views
13

Tôi có 2 API mà tôi muốn yêu cầu theo thứ tự và lưu trữ dữ liệu của chúng trong SQLite.Yêu cầu chuỗi trong Retrofit + RxJava

Trước tiên, tôi muốn yêu cầu API A và lưu trữ dữ liệu trong bảng SQL a. Sau đó, yêu cầu API B và lưu trữ dữ liệu trong bảng b và một số dữ liệu trong bảng a_b. Các dữ liệu được lưu trữ trong a_b là từ yêu cầu B một mình.

Làm cách nào tôi có thể thực hiện việc này bằng RxJava. Tôi đọc ở đâu đó về việc sử dụng flatMap cho điều này, một cái gì đó như thế này

apiService.A() 
    // store in DB here? How? maybe use map()? 
    .flatMap(modelA -> { 
     // or maybe store modelA in DB here? 
     return apiService.B().map(modelB -> { 
      storeInDB()l // store B here ? 
      return modelB; 
     }); 
    }); 

Nếu tôi không sử dụng hàm lambda, điều này sẽ trông xấu xí như cuộc gọi lồng nhau bình thường. Đây có phải là cách tốt hơn để làm điều đó không?

Trả lời

13

Tôi không nghĩ rằng sử dụng map điều hành là cách tốt nhất để đi với những thứ như lưu trữ các kết quả của các cuộc gọi api.

Điều tôi muốn làm là phân tách những thứ đó bên trong các toán tử doOnNext. Vì vậy, ví dụ của bạn sẽ là một cái gì đó như thế này:

apiService.A() 
     .doOnNext(modelA -> db.store(modelA)) 
     .flatMap(modelA -> apiService.B()) 
     .doOnNext(modelB -> db.store(modelB)); 

(thêm cần thiết observeOnsubscribeOn mình, hệt như bạn cần họ)

+0

Tôi không biết về các toán tử 'do' của Rx. Sau khi đọc tài liệu của nó, không phải là 'doOnComplete' một chức năng tốt hơn cho điều này? – Sourabh

+0

@Sourabh nó phụ thuộc vào 'Observable' của bạn. Nếu 'onComplete' được gọi sau khi một cuộc gọi thành công từ api, thì có. Nếu 'Observable' của bạn có thể phát ra nhiều sự kiện, thì bạn nên vào' doOnNext'. Trong trường hợp của bạn ('Retrofit') sử dụng' doOnNext' và 'doOnComplete' sẽ có cùng kết quả, nhưng thực sự' doOnComplete' có thể trực quan hơn một chút (tôi đã sử dụng 'doOnNext' trong thói quen thuần túy). –

+0

Ý tôi là, sử dụng 'doOnComplete' thay vì' flatMap' – Sourabh

18

Có, bạn có thể sử dụng bản đồ phẳng cho mục đích chính xác này. Xem ví dụ dưới đây (Giả sử dịch vụ của bạn Một trả Observable<FooA> và dịch vụ B trả Observable<FooB>)

api.serviceA() 
     .flatMap(new Func1<FooA, Observable<FooB>>() { 
      @Override 
      public Observable<FooB> call(FooA fooA) { 
       // code to save data from service A to db 

       // call service B 
       return api.serviceB(); 
      } 
     }) 
     .subscribeOn(Schedulers.io()) 
     .observeOn(AndroidSchedulers.mainThread()) 
     .subscribe(new Subscriber<FooB>() { 
      @Override 
      public void onCompleted() { 
      } 

      @Override 
      public void onError(Throwable e) { 

      } 

      @Override 
      public void onNext(FooB fooB) { 
       // code to save data from service B to db 

      } 
     }); 
+0

Nếu tôi viết code để lưu dữ liệu vào DB trong onNext nó sẽ chạy trên chủ đề chính đúng? Làm cách nào để lưu dữ liệu vào db trên luồng nền thay thế? –

+0

ném vào một toán tử 'flatMap' khác. 'api.serviceA(). flatMap ((FooA) -> {// gọi dịch vụ B}). flatMap ((FooB) -> {// lưu dữ liệu từ dịch vụ B và trả về một thành công có thể quan sát được/thất bại}). (Schedulers.io()) Quan sát (AndroidSchedulers.mainThread()) doOnNext ((isSuccess) -> {// Chỉ điều này sẽ thực hiện trên thread chính}) ' –

+0

Bạn sẽ làm điều này như thế nào trong RxJava2? – Ryan

Các vấn đề liên quan