2014-07-16 16 views
9

Używam Retrofit do zwracania rxjava Observable dla moich asynchronicznych połączeń sieciowych.Domyślne harmonogramy dla rxjava na Androidzie

znajdę się powtarzać następujące wezwanie:

someApiCall().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())

Wydaje się jakbym zawsze subskrypcji na gwincie IO i obserwując na Androida głównego wątku. Wydaje się, że jest to najlepsza praktyka, którą zalecają wszystkie zasoby, które znalazłem. Być może poza długotrwałymi obliczeniami, nie bardzo rozumiem, kiedy chcielibyśmy odejść od tego schematu.

Czy istnieje sposób usunięcia tego elementu domyślnego za pomocą opcji subscribeOn i observeOn?

Czy to jest przypadek użycia dla rxjava plugins? (Nie mogę znaleźć wielu przykładów ich użycia.)

Czy mogę ustawić domyślne wątki na granicy sieci, łącząc się z retrofit executors?

+0

Zobacz moje pytanie/odpowiedź tutaj, w jaki sposób DRY to nieco: http://stackoverflow.com/a/25576177 – ktusznio

Odpowiedz

10

Dla odpowiedzi Observable, Retrofit obecnie ustawia subscribeOn jako wykonawcę HTTP dla RestAdapter (dostarczonego lub domyślnego). Zostało to zrobione w celu wsparcia RxJava w istniejącym zachowaniu.

Plan dla wersji 2.0 to zapewnienie możliwości domyślnego ustawienia wartości domyślnych zarówno dla subscribeOn, jak i dla observeOn (niezależnie od tego, czy jest to jedno, czy drugie).

Powodem, dla którego nie chcesz, aby zawsze była obserwowana w głównym wątku, jest na przykład połączenie wielu połączeń API.

+0

w wersji 1.9, stwierdziłem, że nie wywoływanie 'subscribeOn (something)' (zwykle 'Schedulers.io()') podczas testów impasu testów. Czy to oczekiwane zachowanie? – njzk2

4

Wersja 01.wersji 2.0.0-beta2 (2015-09-28) pokazuje subscribeOn() jest wymagany do działania w tle.

Poprawka: obserwowalne i pojedyncza realizacja żądań teraz zachowują się synchronicznie (i dlatego wymaga subscribeOn() do działania w tle).

2

Tak, możliwe jest usunięcie obu połączeń.

Oto klasa adapter retrofit, że aby usunąć automatycznie harmonogramy zarówno subscribeOn i observedOn potrzebę połączeń boilerplate w każdej inwokacji:

public class RxThreadingCallAdapterFactory extends CallAdapter.Factory { 
    private final RxJava2CallAdapterFactory original; 

    private RxThreadingCallAdapterFactory() { 
     // Always call on background thread 
     original = RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()); 
    } 

    public static CallAdapter.Factory create() { 
     return new RxThreadingCallAdapterFactory(); 
    } 

    @Override 
    public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { 
     return new RxCallAdapterWrapper(original.get(returnType, annotations, retrofit)); 
    } 

    private static class RxCallAdapterWrapper implements CallAdapter<Observable<?>> { 
     private final CallAdapter<?> wrapped; 

     public RxCallAdapterWrapper(CallAdapter<?> wrapped) { 
      this.wrapped = wrapped; 
     } 

     @Override 
     public Type responseType() { 
      return wrapped.responseType(); 
     } 

     @Override 
     public <R> Observable<?> adapt(Call<R> call) { 
      Observable observable = (Observable) wrapped.adapt(call); 

      // Always handle result on main thread 
      return observable.observeOn(AndroidSchedulers.mainThread()); 
     } 
    } 
} 

Następnie za pomocą tej karty podczas konfigurowania doposażenia:

Retrofit.Builder() 
    .baseUrl(...) 
    .addCallAdapterFactory(RxThreadingCallAdapterFactory.create()) 

Napisałem this blog post, który szczegółowo opisuje, co się tutaj dzieje.

Spowoduje to usunięcie obu połączeń, które uważam za obowiązujące. Uważam, że scenariusz Jake'a łączenia połączeń w tle nie ma zastosowania, ponieważ w tym przypadku wykonałbym synchronizację połączeń i nie używałbym w ogóle programów do planowania.