Powiedzmy interfejs zdefiniowano dla Retrofit zawiera metody takie jak to:
public Observable<GameState> loadGameState(@Query("id") String gameId);
metody modernizacyjnej można określić w jeden z trzech sposobów:
1.) prosty synchronicznej One:
public GameState loadGameState(@Query("id") String gameId);
2.), który wziąć Callback
dla asynchronicznego użytkowania:
public void loadGameState(@Query("id") String gameId, Callback<GameState> callback);
3.) i ten, który zwraca rxjava Observable
, patrz wyżej. Myślę, że jeśli zamierzasz używać Retrofit w połączeniu z rxjava, to ma sens używanie tej wersji.
ten sposób można po prostu użyć obserwowalne dla pojedynczego żądania bezpośrednio tak:
mApiService.loadGameState(mGameId)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<GameState>() {
@Override
public void onNext(GameState gameState) {
// use the current game state here
}
// onError and onCompleted are also here
});
Jeśli chcesz wielokrotnie odpytywać serwer przy użyciu można zapewnić „puls”, używając wersji timer()
lub interval()
:
Observable.timer(0, 2000, TimeUnit.MILLISECONDS)
.flatMap(mApiService.loadGameState(mGameId))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<GameState>() {
@Override
public void onNext(GameState gameState) {
// use the current game state here
}
// onError and onCompleted are also here
}).
ważne jest, aby pamiętać, że używam flatMap
tutaj zamiast map
- to dlatego, że wartość zwracana loadGameState(mGameId)
sama jest Observable
.
Ale wersja używasz w swojej aktualizacji powinno działać zbyt:
Observable.interval(2, TimeUnit.SECONDS, Schedulers.io())
.map(tick -> Api.ReceiveGameTurn())
.doOnError(err -> Log.e("Polling", "Error retrieving messages" + err))
.retry()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(sub);
Oznacza to, że jeśli ReceiveGameTurn()
definiuje synchronicznie jak mój 1.) powyżej, należy użyć map
zamiast flatMap
.
W obu przypadkach onNext
twojego Subscriber
będzie wywoływane co dwie sekundy z najnowszym stanem gry z serwera. Możesz przetwarzać je jeden po drugim, ograniczając emisję do pojedynczego elementu, wstawiając take(1)
przed subscribe()
.
Jednakże, w odniesieniu do pierwszej wersji: Jeden błąd sieci byłby pierwszy dostarczana do onError
a następnie obserwowalnym zatrzyma emitując żadnych więcej przedmiotów, czyniąc abonent bezużyteczna i bez wejścia (pamiętaj, onError
może być wywołana tylko raz). Aby obejść ten problem, można użyć dowolnej z metod rxjava, aby "przekierować" niepowodzenie na onNext.
Na przykład:
Observable.timer(0, 2000, TimeUnit.MILLISECONDS)
.flatMap(new Func1<Long, Observable<GameState>>(){
@Override
public Observable<GameState> call(Long tick) {
return mApiService.loadGameState(mGameId)
.doOnError(err -> Log.e("Polling", "Error retrieving messages" + err))
.onErrorResumeNext(new Func1<Throwable, Observable<GameState>(){
@Override
public Observable<GameState> call(Throwable throwable) {
return Observable.emtpy());
}
});
}
})
.filter(/* check if it is a valid new game state */)
.take(1)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<GameState>() {
@Override
public void onNext(GameState gameState) {
// use the current game state here
}
// onError and onCompleted are also here
}).
Będzie co dwie sekundy: * Zastosowanie Retrofit aby uzyskać aktualny stan gry z serwera * odfiltrowanie nieprawidłowych ones * podejmują pierwsze ważne jedną * i wypisać
w przypadku błędu: * wypisze komunikat o błędzie w doOnNext
* a inaczej zignorować błąd: onErrorResumeNext
będzie „konsumować” z onError
-Event (tj. twoje Subscriber
's onError
nie będą wywoływane) i zastępuje je z niczym (Observable.empty()
).
I, w odniesieniu do drugiego wersję: W przypadku błędu sieci retry
natychmiast ponownie zarejestrować się w przedziale - a ponieważ interval
emituje pierwszy Integer natychmiast po subskrypcji kolejna prośba zostanie wysłana natychmiast, za - i nie po 3 sekundach jak prawdopodobnie chcesz ...
Ostatnia uwaga: Jeśli twój stan gry jest dość duży, możesz najpierw odpytać serwer, aby zapytać, czy nowy stan jest dostępny i tylko w przypadku pozytywnej odpowiedzi przeładuj nowy stan gry.
Jeśli potrzebujesz bardziej wyszukanych przykładów, zapytaj.
AKTUALIZACJA: Przepisałem części tego wpisu i dodałem więcej informacji pomiędzy.
UPDATE 2: Dodałem pełny przykład obsługi błędów z onErrorResumeNext
.
Nie potrzebujesz * potrzebujesz * RxJava. Ale dobrze radzi sobie z modernizacją. – njzk2
Jak mogę przeprowadzić pobieranie z Retrofitem bez RxJavy? – mrpool89