Lassen Sie uns sagen, dass die Schnittstelle, die Sie für Retrofit definiert eine Methode wie folgt enthält:
public Observable<GameState> loadGameState(@Query("id") String gameId);
Nachrüstverfahren können in eine von drei Arten definiert werden:
1.) eine einfache synchrone ein:
public GameState loadGameState(@Query("id") String gameId);
2.) ein, die ein Callback
für asynchrone Handhabung nehmen:
public void loadGameState(@Query("id") String gameId, Callback<GameState> callback);
3.) und die, die einen rxjava Observable
zurückgibt, siehe oben. Ich denke, wenn Sie Retrofit in Verbindung mit rxjava verwenden, ist es am sinnvollsten, diese Version zu verwenden.
Auf diese Weise können nur die beobachtbaren für eine einzige Anforderung wie diese direkt verwenden:
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
});
Wenn Sie wiederholt den Server abzufragen verwenden Sie die „Impuls“ zur Verfügung stellen kann Versionen von timer()
oder interval()
mit:
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
}).
Es ist wichtig, dass ich flatMap
hier statt map
bin mit zu beachten - das ist, weil der Rückgabewert von loadGameState(mGameId)
selbst ein 012.313..
Aber die Version, die Sie in Ihrem Update verwenden, sollten auch funktionieren:
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);
Das heißt, wenn ReceiveGameTurn()
synchron wie mein 1. definiert ist) oben, würden Sie map
statt flatMap
verwenden.
In beiden Fällen würde die onNext
Ihrer Subscriber
alle zwei Sekunden mit dem neuesten Spielstand vom Server aufgerufen werden. Sie können sie nacheinander verarbeiten, um die Emission auf einen einzelnen Artikel zu beschränken, indem Sie take(1)
vor subscribe()
einfügen.
jedoch in Bezug auf die erste Version: Ein einzelner Netzwerkfehler zuerst onError
geliefert werden würde, und dann würde die beobachtbare stoppen noch mehr Produkte zu emittieren, Ihre Abonnenten nutzlos und ohne Eingabe Rendering (denken Sie daran, onError
nur einmal aufgerufen werden kann). Um dies zu umgehen, können Sie eine der onError*
Methoden von rxjava verwenden, um den Fehler auf onNext umzuleiten.
Zum Beispiel:
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
}).
Dies werden alle zwei Sekunden: * Verwendung Retrofit den aktuellen Spielzustand vom Server * herauszuzufiltern ungültig derjenigediejenigedasjenige * nehmen Sie die ersten gültigen * zu erhalten und die abmelden
im Fall eines Fehlers: * es wird eine Fehlermeldung in doOnNext
* und ansonsten ignoriert die Fehler drucken: onErrorResumeNext
wird „verbrauchen“ die onError
-Event (d.h. Ihre Subscriber
's onError
wird nicht aufgerufen) und ersetzt sie durch nichts (Observable.empty()
).
Und die zweite Version in Bezug auf: Im Falle eines Netzwerkfehlers retry
dem Intervall unmittelbar resubscribe würde - und da interval
die erste Integer sofort bei der Zeichnung emittiert die nächste Anforderung würde sofort auch gesendet werden - und nicht nach 3 Sekunden wie Sie wahrscheinlich wollen ...
Schlussbemerkung: Auch wenn Ihr Spielzustand ziemlich groß ist, könnten Sie auch zuerst den Server fragen, ob ein neuer Zustand verfügbar ist und nur im Falle einer positiven Antwort den neuer Spielstatus
Wenn Sie ausführlichere Beispiele benötigen, fragen Sie bitte.
AKTUALISIEREN: Ich habe Teile dieses Beitrags umgeschrieben und dazwischen weitere Informationen hinzugefügt.
UPDATE 2: Ich habe ein vollständiges Beispiel der Fehlerbehandlung mit onErrorResumeNext
hinzugefügt.
Sie brauchen * RxJava * nicht. Aber es funktioniert gut mit Retrofit. – njzk2
Wie implementiere ich die Abfrage mit Retrofit ohne RxJava? – mrpool89