Wie handle paging mit RxJava?
Ich bin auf der Suche in der Umstellung meiner android app zu verwenden Rxjava für Netzwerk-Anforderungen. Ich habe derzeit Zugriff auf einen webservice ähnlich:
getUsersByKeyword(String query, int limit, int offset)
Als ich verstehen es, Observablen sind ein "push" und nicht als "pull" - Schnittstelle. So, hier ist, wie ich die Dinge verstehen zu funktionieren:
- app registriert mit service, immer Beobachtbar für Abfrage
- Ergebnisse geschoben werden app
- app befasst sich mit den Ergebnissen
- wenn die app will mehr Ergebnissen ...?
Dies ist, wo die Dinge brechen für mich. Vorher würde ich nur bitten, den webservice für genau das, was ich will, machen Sie die Abfrage erneut mit dem offset. Aber in diesem Fall, dass würde bedeuten, die Schaffung einer anderen Beobachtbaren und abonnieren Sie irgendwie besiegen den Punkt.
Wie soll ich handle paging in meine app? (Es ist eine android app, aber ich denke nicht, dass das relevant ist).
Du musst angemeldet sein, um einen Kommentar abzugeben.
War es hard rock!)
So haben wir die Anfrage zum Netzwerk:
getUsersByKeyword(String query, int limit, int offset)
und dieser Wunsch zurückzukehren, zum Beispiel
List< Result >
Wenn wir die Nachrüstung für die Vernetzung, die Anfrage Aussehen wird:
Observable< List< Result >> getUsersByKeyword(String query, int limit, int offset)
Als Ergebnis wollen wir alle
Result
vom server.Also wird es so Aussehen
Code wurde GETESTET!
getUsersByKeyword
gibt, die weniger Elemente als der Seite Größe (50 hier), dann 1 übermäßige Aufruf zur nächsten Seite gemacht werden, sowieso. 2. Wenn diegetUsersByKeyword
gibt keine Elemente für die Seite 1, dann die exception wird geworfen:java.util.NoSuchElementException
. Erwägen Sie die Verwendung.lastOrDefault(new ArrayList<>())
statt.last()
Also, wenn das ein-Wege-paging, hier ist ein Muster, das Sie versuchen könnten. Dieser code wurde nicht ausgeführt oder kompiliert, aber ich habe versucht, über-kommentieren, um zu erklären, was Los ist.
Sollte lassen Sie die "nächste Seite" events " - signal trigger-ein laden der nächsten Seite die Daten zu jeder Zeit, so gut wie nicht springen Seiten sollte es ein Fehler auftreten, laden ein. Es auch wieder ganz auf der obersten Ebene, wenn es erhält eine neue Suchabfrage. Wenn ich (oder jemand anderes?) hat Zeit, ich möchte prüfen, meine Annahmen über das Trampolin und Gegendruck und sicherstellen, dass es blockiert jeden Versuch vorzeitig zu Holen der nächsten Seite beim laden.
trampoline
gefolgt vonio
so funktioniert? Ich sah auch Ihre Diskussion über auf Github, konnte es aber nicht, Schlussfolgerungen aus dort.Ich habe dies getan, und es ist eigentlich nicht schwer.
Der Ansatz ist um modellieren, jeden ersten Anfrage (offset 0) in einem firstRequestsObservable. Um es einfach, können Sie diese als PublishSubject, wo Sie anrufen
onNext()
füttern Sie in der nächsten Anforderung, aber es gibt intelligentere nicht-Subjekt Möglichkeiten, es zu tun (z.B. wenn die Anfragen werden gemacht, wenn ein button angeklickt wird, dann wird die requestObservable ist die clickObservable abgebildet durch einige Operatoren).Sobald Sie
firstRequestsObservable
im Ort können Sie machenresponseObservable
durch flatMapping vonfirstRequestsObservable
und so weiter, damit der service-Aufruf.Hier kommt nun der trick: machen Sie eine weitere observable genannt
subsequentRequestsObservable
denen zugeordnet, vonresponseObservable
inkrementiert den offset (für diesen Zweck ist es gut zu gehören, in den response-Daten, den offset von der ursprünglichen Anfrage). Sobald Sie die Einführung dieses observable haben, müssen Sie nun ändern Sie die definition vonresponseObservable
so dass es hängt auch vonsubsequentRequestsObservable
. Sie erhalten dann eine zirkuläre Abhängigkeit wie diese:firstRequestsObservable -> responseObservable -> subsequentRequestsObservable -> responseObservable -> subsequentRequestsObservable -> ...
Brechen dieses Zyklus, werden Sie wahrscheinlich wollen, um eine
filter
Betreiber bei der definition vonsubsequentRequestsObservable
herausfiltern jenen Fällen, wo das offset an der "total" - Grenze. Die zirkuläre Abhängigkeit bedeutet auch, dass Sie müssen zu haben, einer von denen, die ein Thema, sonst wäre es unmöglich zu erklären, dass die observablen. Ich empfehleresponseObservable
zu diesem Thema.So, alles in allem, Sie zunächst initialisieren responseObservable als ein Thema, dann erklären firstRequestsObservable, dann erklären subsequentRequestsObservable als Ergebnis übergeben responseObservable durch einige Betreiber. responseObservable kann dann "gefüttert", indem
onNext
.requestMoreResultsObservable
abhängenscrollBottomHappenedObservable
undresponseObservable
. Alles sollten modelliert werden als eine Beobachtbare. So etwas wierequestMoreResultsObservable = responseObservable.sample(scrollBottomHappenedObservable).map(// get the last response, increment offset, return request url
. Lesen Sie die Antwort wieder. Denke nur in Marmor-Diagramme, z.B., rxmarbles.com , vorstellen, dass die observablen sind spreadsheet-Zellen und stellen Sie voneinander abhängen. Es scheint, dass das, was Sie brauchen, ist eine Veränderung der Denkweise zu bekommen alte Imperativ Gewohnheiten entfernt.Klar zu sein, ich nehme an, Ihr Fragen ist vielmehr, wie sich zu bewerben RxJava in Ihrem Android-Anwendung, anstatt auf dem back-end (obwohl es möglich ist, gelten auch, aber nicht so typisch wie die front-end).
Und ich bin mir nicht ganz sicher, ob dieses Beispiel ist ein typischer Anwendungsfall für die Verwendung von reaktiven funktionalen Programmierung (RFP) - Modell, außer für den clean-code-Konstrukte.
Jedem stream unten ist eine Observable. Persönlich würde ich mag zu denken, es als stream, da es einfach zu Grund, über die Ereignisse.
Paginierung flow dargestellt werden kann durch 6 streams:
Den oben genannten streams dargestellt werden können, in pseudo-code (JS Stil) unten (es wäre ziemlich einfach zu übersetzen, um RxJava oder andere Sprachen)
PS1: habe ich nicht getestet, den obigen code. Ich bin Lern-RFP, so kann ich nur versuchen zu denken, in reaktiver Weise durch aufschreiben. Willkommen, jede Anregung.
PS2: ich bin stark beeinflusst von https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 für die Art und Weise zu erklären, reaktive Datenströme.