Filtriranje uočljivih u RxJavi

1. Uvod

Nakon Uvoda u RxJavu, pogledati ćemo operatore filtriranja.

Konkretno, usredotočit ćemo se na filtriranje, preskakanje, vremensko filtriranje i neke naprednije operacije filtriranja.

2. Filtriranje

Pri radu s Uočljiv, ponekad je korisno odabrati samo podskup emitiranih stavki. Za ovu svrhu, RxJava nudi razne mogućnosti filtriranja.

Počnimo gledati filtar metoda.

2.1. The filtar Operater

Jednostavno rečeno, filtar operator filtrira an Uočljiv pazeći da emitirane stavke odgovaraju navedenom stanju, koji dolazi u obliku a Predikat.

Pogledajmo kako možemo filtrirati samo neparne vrijednosti od emitiranih:

Observable sourceObservable = Observable.range (1, 10); Pretplatnik na TestSubscriber = novi TestSubscriber (); Primjetan filteredObservable = sourceObservable .filter (i -> i% 2! = 0); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValues ​​(1, 3, 5, 7, 9);

2.2. The uzeti Operater

Pri filtriranju s uzeti, logika rezultira emisijom prvog n stavki uz zanemarivanje preostalih predmeta.

Pogledajmo kako možemo filtrirati izvorUočljiv i emitiraju samo prve dvije stavke:

Observable sourceObservable = Observable.range (1, 10); Pretplatnik na TestSubscriber = novi TestSubscriber (); Promatrano filtriranoObservable = sourceObservable.take (3); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValues ​​(1, 2, 3);

2.3. The takeWhile Operater

Prilikom korištenja uzmi dok, filtrirani Uočljiv emitirat će stavke sve dok ne naiđe na prvi element koji se ne podudara s Predikat.

Pogledajmo kako možemo koristiti takeWhile - s filtriranjem Predikat:

Observable sourceObservable = Observable.just (1, 2, 3, 4, 3, 2, 1); Pretplatnik na TestSubscriber = novi TestSubscriber (); Observable filteredObservable = sourceObservable .takeWhile (i -> i <4); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValues ​​(1, 2, 3);

2.4. The takeFirst Operater

Kad god želimo emitirati samo prvu stavku koja se podudara s danim uvjetom, možemo je koristiti takeFirst ().

Pogledajmo na brzinu kako možemo emitirati prvu stavku veću od 5:

Observable sourceObservable = Observable .just (1, 2, 3, 4, 5, 7, 6); Pretplatnik na TestSubscriber = novi TestSubscriber (); Observable filteredObservable = sourceObservable .takeFirst (x -> x> 5); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValue (7);

2.5. prvi i firstOrDefault Operateri

Slično ponašanje može se postići korištenjem prvi API:

Observable sourceObservable = Observable.range (1, 10); Pretplatnik na TestSubscriber = novi TestSubscriber (); Promatrano filteredObservable = sourceObservable.first (); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValue (1);

Međutim, u slučaju da želimo odrediti zadanu vrijednost, ako se ne emitiraju stavke, možemo koristiti firstOrDefault:

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

2.6. The takeLast Operater

Dalje, ako želimo emitirati samo posljednje n stavke koje emitira Uočljiv, možemo koristiti takeLast.

Pogledajmo kako je moguće emitirati samo posljednje tri stavke:

Observable sourceObservable = Observable.range (1, 10); Pretplatnik na TestSubscriber = novi TestSubscriber (); Promatrano filtriranoObservable = sourceObservable.takeLast (3); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValues ​​(8, 9, 10);

Moramo imati na umu da ovo odgađa emisiju bilo kojeg predmeta iz izvora Uočljiv dok se ne dovrši.

2.7. posljednji i lastOrDefault

Ako želimo emitirati samo posljednji element, drugi onda pomoću takeLast (1), možemo koristiti posljednji.

Ovo filtrira Uočljiv, emitirajući samo zadnji element, koji po želji provjerava filtriranje Predikat:

Observable sourceObservable = Observable.range (1, 10); Pretplatnik na TestSubscriber = novi TestSubscriber (); Primjetan filteredObservable = sourceObservable .last (i -> i% 2! = 0); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValue (9);

U slučaju da Uočljiv je prazno, možemo ga koristiti lastOrDefault, koji filtrira Uočljiv emitirajući zadanu vrijednost.

Zadana vrijednost također se emitira ako lastOrDefault koristi se operator i nema stavki koje potvrđuju stanje filtriranja:

Observable sourceObservable = Observable.range (1, 10); Pretplatnik na TestSubscriber = novi TestSubscriber (); Observable filteredObservable = sourceObservable.lastOrDefault (-1, i -> i> 10); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValue (-1);

2.8. elementAt i elementAtOrDefault Operateri

Uz elementAt operatora, možemo odabrati jednu stavku koju emitira izvor Uočljiv, navodeći njegov indeks:

Observable sourceObservable = Observable .just (1, 2, 3, 5, 7, 11); Pretplatnik na TestSubscriber = novi TestSubscriber (); Observable filteredObservable = sourceObservable.elementAt (4); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValue (7);

Međutim, elementAt bacit će IndexOutOfBoundException ako navedeni indeks premašuje broj emitiranih predmeta.

Da biste izbjegli ovu situaciju, moguće je koristiti elementAtOrDefault - koji će vratiti zadanu vrijednost u slučaju da je indeks izvan raspona:

Observable sourceObservable = Observable .just (1, 2, 3, 5, 7, 11); Pretplatnik na TestSubscriber = novi TestSubscriber (); Observable filteredObservable = sourceObservable.elementAtOrDefault (7, -1); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValue (-1);

2.9. The ofType Operater

Kad god Uočljiv emitira Objekt stavke moguće ih je filtrirati na temelju njihove vrste.

Pogledajmo kako možemo samo filtrirati Niz vrsta emitiranih predmeta:

Observable sourceObservable = Observable.just (1, "dva", 3, "pet", 7, 11); Pretplatnik na TestSubscriber = novi TestSubscriber (); Observable filteredObservable = sourceObservable.ofType (String.class); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValues ​​("dva", "pet");

3. Preskakanje

S druge strane, kada želimo filtrirati ili preskočiti neke stavke koje emitira Uočljiv, RxJava nudi nekoliko operatora kao pandan onima za filtriranje, o čemu smo prethodno razgovarali.

Počnimo gledati preskočiti operater, pandan uzeti.

3.1. The preskočiti Operater

Kad an Uočljiv emitira slijed stavki, moguće je filtrirati ili preskočiti neke od emitiranih stavki pomoću preskočiti.

Na primjer. pogledajmo kako je moguće preskočiti prva četiri elementa:

Observable sourceObservable = Observable.range (1, 10); Pretplatnik na TestSubscriber = novi TestSubscriber (); Promatrano filtriranoObservable = sourceObservable.skip (4); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValues ​​(5, 6, 7, 8, 9, 10);

3.2. The preskočiDok Operater

Kad god želimo filtrirati sve prve vrijednosti koje emitira Uočljiv koji ne uspiju predikat filtriranja, možemo koristiti preskočiDok operater:

Observable sourceObservable = Observable .just (1, 2, 3, 4, 5, 4, 3, 2, 1); Pretplatnik na TestSubscriber = novi TestSubscriber (); Observable filteredObservable = sourceObservable .skipWhile (i -> i <4); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValues ​​(4, 5, 4, 3, 2, 1);

3.3. The preskočiPosljednji Operater

The preskočiPosljednji Operator omogućuje nam preskakanje konačnih stavki koje emitira Uočljiv prihvaćajući samo one emitirane prije njih.

Ovim možemo, na primjer, preskočiti posljednjih pet stavki:

Observable sourceObservable = Observable.range (1, 10); Pretplatnik na TestSubscriber = novi TestSubscriber (); Promatrano filtriranoObservable = sourceObservable.skipLast (5); filteredObservable.subscribe (pretplatnik); pretplatnik.assertValues ​​(1, 2, 3, 4, 5);

3.4. različit i distinctUntilChanged Operateri

The različit operator vraća an Uočljiv koji emitira sve predmete koje emitira izvorObservable koji su različiti:

Observable sourceObservable = Observable .just (1, 1, 2, 2, 1, 3, 3, 1); Pretplatnik na TestSubscriber = novi TestSubscriber (); Opažljivo razlikovitoObservable = sourceObservable.distinct (); distinctObservable.subscribe (pretplatnik); pretplatnik.assertValues ​​(1, 2, 3);

Međutim, ako želimo dobiti Uočljiv koji emitira sve predmete koje emitira izvorObservable koji se razlikuju od njihovog neposrednog prethodnika, možemo koristiti distinctUntilChanged operater:

Observable sourceObservable = Observable .just (1, 1, 2, 2, 1, 3, 3, 1); Pretplatnik na TestSubscriber = novi TestSubscriber (); Uočljivo razlikovitoObservable = sourceObservable.distinctUntilChanged (); distinctObservable.subscribe (pretplatnik); pretplatnik.assertValues ​​(1, 2, 1, 3, 1);

3.5. The ignoreElements Operater

Kad god želimo zanemariti sve elemente koje emitira izvorObservable, možemo jednostavno koristiti ignoreElements:

Observable sourceObservable = Observable.range (1, 10); Pretplatnik na TestSubscriber = novi TestSubscriber (); Observable ignoredObservable = sourceObservable.ignoreElements (); ignoredObservable.subscribe (pretplatnik); pretplatnik.assertNoValues ​​();

4. Operateri filtriranja vremena

Pri radu s uočljivim slijedom vremenska os je nepoznata, ali ponekad bi korisno bilo dobivanje pravovremenih podataka iz niza.

U tu svrhu, RxJava nudi nekoliko metoda koje nam omogućuju rad Uočljiv koristeći također vremensku os.

Prije nego što prijeđemo na prvu, definirajmo vrijeme Uočljiv koji će emitirati stavku svake sekunde:

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

The TestScheduler je poseban rokovnik koji omogućuje ručno pomicanje sata bilo kojim tempom koji više volimo.

4.1. uzorak i throttleLast Operateri

The uzorak operator filtrira temedObservable, vraćajući an Uočljiv koji emitira najnovije stavke koje ovaj API emitira u vremenskim intervalima.

Pogledajmo kako možemo uzorkovati temedObservable, filtrirajući samo posljednju emitiranu stavku svake 2,5 sekunde:

Pretplatnik na TestSubscriber = novi TestSubscriber (); Uočljiv sampledObservable = timedObservable .sample (2500L, TimeUnit.MILLISECONDS, testScheduler); sampledObservable.subscribe (pretplatnik); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); pretplatnik.assertValues ​​(3, 5, 6);

Ovakvo ponašanje može se postići i pomoću throttleLast operater.

4.2. The gasPrvi Operater

The gasPrvi operator razlikuje se od throttleLast / sample budući da emitira prvu stavku koju emitira temedObservable u svakom razdoblju uzorkovanja umjesto u posljednjem emitiranom.

Pogledajmo kako možemo emitirati prve stavke, koristeći razdoblje uzorkovanja od 4 sekunde:

Pretplatnik na TestSubscriber = novi TestSubscriber (); Primjetan filteredObservable = timedObservable .throttleFirst (4100L, TimeUnit.SECONDS, testScheduler); filteredObservable.subscribe (pretplatnik); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); pretplatnik.assertValues ​​(1, 6);

4.3. rasklinjanje i throttleWithTimeout Operateri

Uz rasklinjanje operatora, moguće je emitirati samo stavku ako je određeni vremenski raspon prošao bez emitiranja druge stavke.

Stoga, ako odaberemo vremenski raspon koji je veći od vremenskog intervala između emitiranih stavki temedObservable, emitirat će samo posljednju. S druge strane, ako je manji, emitirat će sve stavke koje emitira temedObservable.

Pogledajmo što će se dogoditi u prvom scenariju:

Pretplatnik na TestSubscriber = novi TestSubscriber (); Primjetan filteredObservable = timedObservable .debounce (2000L, TimeUnit.MILLISECONDS, testScheduler); filteredObservable.subscribe (pretplatnik); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); pretplatnik.assertValue (6);

Ovakvo ponašanje također se može postići korištenjem throttleWithTimeout.

4.4. The pauza Operater

The pauza operator zrcali izvor Uočljiv, ali izdaju obavijest o pogrešci, prekidajući emisiju predmeta, ako je izvor Uočljiv ne emitira nijednu stavku tijekom određenog vremenskog intervala.

Pogledajmo što će se dogoditi ako odredimo vremensko ograničenje od 500 milisekundi temedObservable:

Pretplatnik na TestSubscriber = novi TestSubscriber (); Primjetljivo filteredObservable = timedObservable .timeout (500L, TimeUnit.MILLISECONDS, testScheduler); filteredObservable.subscribe (pretplatnik); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); pretplatnik.assertError (TimeoutException.class); pretplatnik.assertValues ​​(1);

5. Višestruko uočljivo filtriranje

Pri radu s Uočljiv, definitivno je moguće odlučiti filtrirati ili preskočiti stavke na temelju sekunde Uočljiv.

Prije nego krenemo dalje, definirajmo a odgođenoOpažljivo, koji će emitirati samo 1 predmet nakon 3 sekunde:

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

Krenimo od takeUntil operater.

5.1. The takeUntil Operater

The takeUntil operator odbacuje bilo koju stavku koju je emitirao izvor Uočljiv (temedObservable) nakon sekunde Uočljiv (odgođenoOpažljivo) emitira stavku ili završava:

Pretplatnik na TestSubscriber = novi TestSubscriber (); Observable filteredObservable = timedObservable .skipUntil (odgođenoObservable); filteredObservable.subscribe (pretplatnik); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); pretplatnik.assertValues ​​(4, 5, 6);

5.2. The preskočiUni Operater

S druge strane, preskočiUni odbacuje bilo koju stavku koju je emitirao izvor Uočljiv (temedObservable) do sekunde Uočljiv (odgođenoOpažljivo) emitira stavku:

Pretplatnik na TestSubscriber = novi TestSubscriber (); Observable filteredObservable = timedObservable .takeUntil (odgođenoObservable); filteredObservable.subscribe (pretplatnik); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); pretplatnik.assertValues ​​(1, 2, 3);

6. Zaključak

U ovom opsežnom vodiču istražili smo različite operatore filtriranja dostupne u RxJavi, pružajući jednostavan primjer svakog od njih.

Kao i uvijek, svi primjeri koda u ovom članku mogu se naći na GitHubu.


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