Filtrering af observerbare ting i RxJava

1. Introduktion

Efter introduktionen til RxJava skal vi se på filtreringsoperatorerne.

Især vil vi fokusere på filtrering, springning, tidsfiltrering og nogle mere avancerede filtreringsoperationer.

2. Filtrering

Når du arbejder med Observerbar, nogle gange er det nyttigt kun at vælge et undersæt af emitterede emner. Til dette formål, RxJava tilbyder forskellige filtreringsfunktioner.

Lad os begynde at se på filter metode.

2.1. Det filter Operatør

Kort sagt, den filter operatør filtrerer en Observerbar at sikre, at emitterede emner matcher den angivne tilstand, som kommer i form af en Prædikat.

Lad os se, hvordan vi kun kan filtrere de ulige værdier fra de udsendte:

Observable sourceObservable = Observable.range (1, 10); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable .filter (i -> i% 2! = 0); filteredObservable.subscribe (abonnent); subscriber.assertValues ​​(1, 3, 5, 7, 9);

2.2. Det tage Operatør

Ved filtrering med tage, resulterer logikken i emission af den første n genstande, mens de resterende genstande ignoreres.

Lad os se, hvordan vi kan filtrere kildeObserverbar og udsender kun de to første ting:

Observable sourceObservable = Observable.range (1, 10); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable.take (3); filteredObservable.subscribe (abonnent); subscriber.assertValues ​​(1, 2, 3);

2.3. Det tagMens Operatør

Ved brug tag medens den filtrerede Observerbar vil fortsætte med at udsende emner, indtil det møder et første element, der ikke matcher Prædikat.

Lad os se, hvordan vi kan bruge tagMens - med en filtrering Prædikat:

Observable sourceObservable = Observable.just (1, 2, 3, 4, 3, 2, 1); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable .takeWhile (i -> i <4); filteredObservable.subscribe (abonnent); subscriber.assertValues ​​(1, 2, 3);

2.4. Det tageFørst Operatør

Når vi kun vil udsende det første element, der matcher en given tilstand, kan vi bruge det takeFirst ().

Lad os se hurtigt på, hvordan vi kan udsende det første element, der er større end 5:

Observable sourceObservable = Observable .just (1, 2, 3, 4, 5, 7, 6); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable .takeFirst (x -> x> 5); filteredObservable.subscribe (abonnent); subscriber.assertValue (7);

2.5. først og firstOrDefault Operatører

En lignende adfærd kan opnås ved hjælp af først API:

Observable sourceObservable = Observable.range (1, 10); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable.first (); filteredObservable.subscribe (abonnent); subscriber.assertValue (1);

Men hvis vi vil angive en standardværdi, kan vi bruge, hvis der ikke udsendes nogen emner firstOrDefault:

Observable sourceObservable = Observable.empty (); Observable filteredObservable = sourceObservable.firstOrDefault (-1); filteredObservable.subscribe (abonnent); subscriber.assertValue (-1);

2.6. Det tage sidst Operatør

Dernæst, hvis vi kun vil udsende det sidste n genstande udsendt af en Observerbar, vi kan bruge tage sidst.

Lad os se, hvordan det kun er muligt at udsende de sidste tre emner:

Observable sourceObservable = Observable.range (1, 10); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable.takeLast (3); filteredObservable.subscribe (abonnent); subscriber.assertValues ​​(8, 9, 10);

Vi er nødt til at huske, at dette forsinker emissionen af ​​ethvert emne fra kilden Observerbar indtil den er færdig.

2.7. sidst og lastOrDefault

Hvis vi kun ønsker at udsende det sidste element, andet ved hjælp af tage sidste (1), vi kan bruge sidst.

Dette filtrerer Observerbar, kun udsender det sidste element, som eventuelt verificerer en filtrering Prædikat:

Observable sourceObservable = Observable.range (1, 10); TestSubscriber-abonnent = ny TestSubscriber (); Observerbar filtreretObservable = sourceObservable .last (i -> i% 2! = 0); filteredObservable.subscribe (abonnent); subscriber.assertValue (9);

I tilfælde af at Observerbar er tom, kan vi bruge lastOrDefault, der filtrerer Observerbar udsender standardværdien.

Standardværdien udsendes også, hvis lastOrDefault operatør bruges, og der er ikke nogen genstande, der bekræfter filtreringstilstanden:

Observable sourceObservable = Observable.range (1, 10); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable.lastOrDefault (-1, i -> i> 10); filteredObservable.subscribe (abonnent); subscriber.assertValue (-1);

2.8. elementAt og elementAtOrDefault Operatører

Med elementAt operatør, kan vi vælge et enkelt emne, der udsendes af kilden Observerbarmed angivelse af dets indeks:

Observable sourceObservable = Observable .just (1, 2, 3, 5, 7, 11); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable.elementAt (4); filteredObservable.subscribe (abonnent); subscriber.assertValue (7);

Imidlertid, elementAt vil kaste en IndexOutOfBoundException hvis det angivne indeks overstiger antallet af emitterede emner.

For at undgå denne situation er det muligt at bruge elementAtOrDefault - som returnerer en standardværdi, hvis indekset er uden for området:

Observable sourceObservable = Observable .just (1, 2, 3, 5, 7, 11); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable.elementAtOrDefault (7, -1); filteredObservable.subscribe (abonnent); subscriber.assertValue (-1);

2.9. Det ofType Operatør

Når den Observerbar udsender Objekt varer, er det muligt at filtrere dem baseret på deres type.

Lad os se, hvordan vi kun kan filtrere Snor emitterede type emner:

Observable sourceObservable = Observable.just (1, "two", 3, "five", 7, 11); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable.ofType (String.class); filteredObservable.subscribe (abonnent); subscriber.assertValues ​​("to", "fem");

3. Spring over

På den anden side når vi vil filtrere eller springe nogle af de emner, der udsendes af en Observerbar, RxJava tilbyder et par operatører som en modstykke til filtreringsprogrammerne, som vi tidligere har diskuteret.

Lad os begynde at se på springe operatør, modstykke til tage.

3.1. Det springe Operatør

Når en Observerbar udsender en sekvens af emner, er det muligt at filtrere eller springe nogle af de første emitterede emner over ved hjælp af springe.

For eksempel. lad os se, hvordan det er muligt at springe de første fire elementer over:

Observable sourceObservable = Observable.range (1, 10); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable.skip (4); filteredObservable.subscribe (abonnent); subscriber.assertValues ​​(5, 6, 7, 8, 9, 10);

3.2. Det spring over mens Operatør

Når vi vil filtrere alle de første værdier, der udsendes af en Observerbar der fejler et filtreringspredikat, kan vi bruge spring over mens operatør:

Observable sourceObservable = Observable .just (1, 2, 3, 4, 5, 4, 3, 2, 1); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable .skipWhile (i -> i <4); filteredObservable.subscribe (abonnent); subscriber.assertValues ​​(4, 5, 4, 3, 2, 1);

3.3. Det skipLast Operatør

Det skipLast giver os mulighed for at springe over de endelige emner, der udsendes af Observerbar accepterer kun dem, der udsendes før dem.

Med dette kan vi for eksempel springe de sidste fem punkter over:

Observable sourceObservable = Observable.range (1, 10); TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = sourceObservable.skipLast (5); filteredObservable.subscribe (abonnent); subscriber.assertValues ​​(1, 2, 3, 4, 5);

3.4. tydelig og distinctUntilChanged Operatører

Det tydelig operatør returnerer en Observerbar der udsender alle de emner, der udsendes af kildeObservabel der er forskellige:

Observable sourceObservable = Observable .just (1, 1, 2, 2, 1, 3, 3, 1); TestSubscriber-abonnent = ny TestSubscriber (); Observable distinctObservable = sourceObservable.distinct (); distinctObservable.subscribe (abonnent); subscriber.assertValues ​​(1, 2, 3);

Men hvis vi ønsker at få en Observerbar der udsender alle de emner, der udsendes af kildeObservabel der adskiller sig fra deres nærmeste forgænger, kan vi bruge distinctUntilChanged operatør:

Observable sourceObservable = Observable .just (1, 1, 2, 2, 1, 3, 3, 1); TestSubscriber-abonnent = ny TestSubscriber (); Observable distinctObservable = sourceObservable.distinctUntilChanged (); distinctObservable.subscribe (abonnent); subscriber.assertValues ​​(1, 2, 1, 3, 1);

3.5. Det ignorere elementer Operatør

Når vi vil ignorere alle de elementer, der udsendes af kildeObservabel, vi kan simpelthen bruge ignorere elementer:

Observable sourceObservable = Observable.range (1, 10); TestSubscriber-abonnent = ny TestSubscriber (); Observerbar ignoreretObservable = sourceObservable.ignoreElements (); ignoreretObservable.subscribe (abonnent); subscriber.assertNoValues ​​();

4. Tidsfiltreringsoperatører

Når du arbejder med observerbar sekvens, er tidsaksen ukendt, men nogle gange kan det være nyttigt at få rettidige data fra en sekvens.

Med dette formål RxJava tilbyder et par metoder, der giver os mulighed for at arbejde med Observerbar bruger også tidsaksen.

Før vi går videre til den første, lad os definere en tidsindstillet Observerbar der udsender et element hvert sekund:

TestScheduler testScheduler = ny TestScheduler (); Observable timedObservable = Observable .just (1, 2, 3, 4, 5, 6) .zipWith (Observable.interval (0, 1, TimeUnit.SECONDS, testScheduler), (item, time) -> item);

Det TestScheduler er en speciel planlægning, der gør det muligt at fremme uret manuelt uanset hvilket tempo vi foretrækker.

4.1. prøve og gashåndtag sidst Operatører

Det prøve operatøren filtrerer timedObservable, returnerer en Observerbar der udsender de seneste emner, der er udsendt af denne API inden for tidsintervaller.

Lad os se, hvordan vi kan prøve den timedObservable, filtrerer kun det sidst udsendte emne hvert 2,5 sekund:

TestSubscriber-abonnent = ny TestSubscriber (); Observable sampledObservable = timedObservable .sample (2500L, TimeUnit.MILLISECONDS, testScheduler); sampledObservable.subscribe (abonnent); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(3, 5, 6);

Denne form for adfærd kan opnås også ved hjælp af gashåndtag sidst operatør.

4.2. Det gasspjæld Først Operatør

Det gasspjæld Først operatøren adskiller sig fra throttleLast / prøve da det udsender det første emne, der sendes af timedObservable i hver prøveudtagningsperiode i stedet for den senest udsendte.

Lad os se, hvordan vi kan udsende de første emner ved hjælp af en prøveudtagningsperiode på 4 sekunder:

TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = timedObservable .throttleFirst (4100L, TimeUnit.SECONDS, testScheduler); filteredObservable.subscribe (abonnent); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(1, 6);

4.3. afvise og gashåndtagWithTimeout Operatører

Med afvise operatør, er det kun muligt at udsende et element, hvis en bestemt tidsperiode er gået uden at udsende et andet element.

Derfor, hvis vi vælger et tidsrum, der er større end tidsintervallet mellem de emitterede emner i timedObservable, det udsender kun den sidste. På den anden side, hvis den er mindre, udsender den alle de emner, der udsendes af timedObservable.

Lad os se, hvad der sker i det første scenario:

TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = timedObservable .debounce (2000L, TimeUnit.MILLISECONDS, testScheduler); filteredObservable.subscribe (abonnent); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValue (6);

Denne form for adfærd kan også opnås ved hjælp af throttleWithTimeout.

4.4. Det tiden er gået Operatør

Det tiden er gået operatøren spejler kilden Observerbar, men udsend en meddelelsesfejl, og afbryd emissionen af ​​emner, hvis kilden Observerbar undlader ikke at udsende nogen genstande i et specificeret tidsinterval.

Lad os se, hvad der sker, hvis vi angiver en timeout på 500 millisekunder til vores timedObservable:

TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = timedObservable .timeout (500L, TimeUnit.MILLISECONDS, testScheduler); filteredObservable.subscribe (abonnent); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertError (TimeoutException.class); subscriber.assertValues ​​(1);

5. Flere observerbare filtreringer

Når du arbejder med Observerbar, er det bestemt muligt at beslutte, om der skal filtreres eller springes over varer baseret på et sekund Observerbar.

Lad os definere en, inden vi går videre forsinketObservabel, der kun udsender 1 element efter 3 sekunder:

Observable delayedObservable = Observable.just (1) .delay (3, TimeUnit.SECONDS, testScheduler);

Lad os starte med tage indtil operatør.

5.1. Det tage indtil Operatør

Det tage indtil operatøren kasserer ethvert emne, der udsendes af kilden Observerbar (timedObservable) efter et sekund Observerbar (forsinketObservabel) udsender et emne eller afslutter:

TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = timedObservable .skipUntil (delayedObservable); filteredObservable.subscribe (abonnent); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(4, 5, 6);

5.2. Det spring til Operatør

På den anden side, spring til kasserer ethvert emne, der udsendes af kilden Observerbar (timedObservable) indtil et sekund Observerbar (forsinketObservabel) udsender et emne:

TestSubscriber-abonnent = ny TestSubscriber (); Observable filteredObservable = timedObservable .takeUntil (delayedObservable); filteredObservable.subscribe (abonnent); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(1, 2, 3);

6. Konklusion

I denne omfattende tutorial undersøgte vi de forskellige filtreringsoperatører, der var tilgængelige i RxJava, og giver et simpelt eksempel på hver enkelt.

Som altid kan alle kodeeksemplerne i denne artikel findes på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found