Filtrovanie pozorovateľných súborov v RxJava

1. Úvod

Po úvode do RxJava sa pozrieme na operátory filtrovania.

Zameriame sa najmä na filtrovanie, preskakovanie, filtrovanie času a niektoré pokročilejšie operácie filtrovania.

2. Filtrovanie

Pri práci s Pozorovateľné, niekedy je užitočné vybrať iba podmnožinu emitovaných položiek. Pre tento účel, RxJava ponúka rôzne možnosti filtrovania.

Začnime sa pozerať na filter metóda.

2.1. The filter Prevádzkovateľ

Jednoducho povedané filter operátorské filtre an Pozorovateľné zabezpečiť, aby emitované položky zodpovedali stanoveným podmienkam, ktorá má formu a Predikát.

Pozrime sa, ako môžeme z emitovaných filtrovať iba nepárne hodnoty:

Pozorovateľný zdrojObservable = Pozorovateľný.rozsah (1, 10); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable .filter (i -> i% 2! = 0); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValues ​​(1, 3, 5, 7, 9);

2.2. The vziať Prevádzkovateľ

Pri filtrovaní pomocou vziať, výsledkom logiky je emisia prvého n položky pri ignorovaní zvyšných položiek.

Pozrime sa, ako môžeme filtrovať zdrojPozorovateľné a emitujú iba prvé dve položky:

Pozorovateľný zdrojObservable = Pozorovateľný.rozsah (1, 10); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable.take (3); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValues ​​(1, 2, 3);

2.3. The takeWhile Prevádzkovateľ

Pri použití vziať zatiaľ čo filtrovaný Pozorovateľné bude emitovať položky, kým nenarazí na prvý prvok, ktorý sa nezhoduje s Predikát.

Pozrime sa, ako môžeme použiť takeWhile - s filtrovaním Predikát:

Pozorovateľný zdrojObservable = Observable.just (1, 2, 3, 4, 3, 2, 1); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable .takeWhile (i -> i <4); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValues ​​(1, 2, 3);

2.4. The vziaťPrvé Prevádzkovateľ

Kedykoľvek chceme emitovať iba prvú položku zodpovedajúcu danej podmienke, môžeme použiť takeFirst ().

Poďme sa rýchlo pozrieť na to, ako môžeme emitovať prvú položku, ktorá je väčšia ako 5:

Pozorovateľný zdrojObservable = Observable .just (1, 2, 3, 4, 5, 7, 6); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable .takeFirst (x -> x> 5); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValue (7);

2.5. najprv a firstOrDefault Operátorov

Podobné správanie je možné dosiahnuť pomocou najprv API:

Pozorovateľný zdrojObservable = Pozorovateľný.rozsah (1, 10); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľné filtrovanéObservovateľné = sourceObservable.first (); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValue (1);

Ak však chceme určiť predvolenú hodnotu, pokiaľ nie sú emitované žiadne položky, môžeme použiť firstOrDefault:

Pozorovateľný sourceObservable = Observable.empty (); Pozorovateľný filterObservable = sourceObservable.firstOrDefault (-1); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValue (-1);

2.6. The vziaťPosledné Prevádzkovateľ

Ďalej, ak chceme emitovať iba posledné n predmety emitované Pozorovateľné, môžeme použiť vziaťPosledné.

Pozrime sa, ako je možné emitovať iba posledné tri položky:

Pozorovateľný zdrojObservable = Pozorovateľný.rozsah (1, 10); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľné filtrovanéObservovateľné = sourceObservable.takeLast (3); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValues ​​(8, 9, 10);

Musíme si uvedomiť, že to oneskoruje emisiu akejkoľvek položky zo zdroja Pozorovateľné kým sa nedokončí.

2.7. posledný a lastOrDefault

Ak chceme emitovať iba posledný prvok, iný ako pomocou takeLast (1), môžeme použiť posledný.

Toto filtruje Pozorovateľné, emitujúci iba posledný prvok, ktorý voliteľne overuje filtrovanie Predikát:

Pozorovateľný zdrojObservable = Pozorovateľný.rozsah (1, 10); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable .last (i -> i% 2! = 0); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValue (9);

V prípade, že Pozorovateľné je prázdny, môžeme použiť lastOrDefault, ktorý filtruje Pozorovateľné emitujúca predvolenú hodnotu.

Predvolená hodnota sa vydáva aj v prípade, že lastOrDefault používa sa operátor a nie sú k dispozícii žiadne položky, ktoré by overovali stav filtrovania:

Pozorovateľný zdrojObservable = Pozorovateľný.rozsah (1, 10); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable.lastOrDefault (-1, i -> i> 10); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValue (-1);

2.8. elementAt a elementAtOrDefault Operátorov

Vďaka elementAt operátor, môžeme vybrať jednu položku emitovanú zdrojom Pozorovateľné, s uvedením jeho indexu:

Pozorovateľný zdrojObservable = Observable .just (1, 2, 3, 5, 7, 11); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable.elementAt (4); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValue (7);

Avšak elementAt bude hádzať IndexOutOfBoundException ak zadaný index prekročí počet emitovaných položiek.

Aby sa zabránilo tejto situácii, je možné použiť elementAtOrDefault - ktorá vráti predvolenú hodnotu v prípade, že je index mimo rozsahu:

Pozorovateľný zdrojObservable = Observable .just (1, 2, 3, 5, 7, 11); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable.elementAtOrDefault (7, -1); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValue (-1);

2.9. The typu Prevádzkovateľ

Kedykoľvek Pozorovateľné vyžaruje Objekt položiek je možné filtrovať na základe ich typu.

Pozrime sa, ako môžeme iba filtrovať String typ emitovaných položiek:

Pozorovateľný zdrojObservable = Observable.just (1, „dva“, 3, „päť“, 7, 11); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable.ofType (String.class); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValues ​​("dva", "päť");

3. Preskočenie

Na druhej strane, keď chceme odfiltrovať alebo preskočiť niektoré z položiek emitovaných pomocou Pozorovateľné, RxJava ponúka niekoľko operátorov ako náprotivok tých filtračných, o ktorých sme už hovorili.

Začnime sa pozerať na preskočiť operátor, náprotivok vziať.

3.1. The preskočiť Prevádzkovateľ

Keď sa Pozorovateľné emituje sled položiek, je možné odfiltrovať alebo preskočiť niektoré z prvých emitovaných položiek pomocou preskočiť.

Napríklad. Pozrime sa, ako je možné preskočiť prvé štyri prvky:

Pozorovateľný zdrojObservable = Pozorovateľný.rozsah (1, 10); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable.skip (4); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValues ​​(5, 6, 7, 8, 9, 10);

3.2. The preskočiť Prevádzkovateľ

Kedykoľvek chceme odfiltrovať všetky prvé hodnoty emitované znakom Pozorovateľné ktoré zlyhajú filtračný predikát, môžeme použiť preskočiť operátor:

Pozorovateľný zdrojObservable = Observable .just (1, 2, 3, 4, 5, 4, 3, 2, 1); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable .skipWhile (i -> i <4); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValues ​​(4, 5, 4, 3, 2, 1);

3.3. The skipLast Prevádzkovateľ

The skipLast operátor nám umožňuje preskočiť konečné položky emitované Pozorovateľné prijímať iba tie, ktoré boli emitované pred nimi.

Vďaka tomu môžeme napríklad preskočiť posledných päť položiek:

Pozorovateľný zdrojObservable = Pozorovateľný.rozsah (1, 10); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = sourceObservable.skipLast (5); filtrovanyobslužnýsubscribe (predplatiteľ); subscriber.assertValues ​​(1, 2, 3, 4, 5);

3.4. odlišný a zreteľný, kým sa nezmení Operátorov

The odlišný operátor vráti Pozorovateľné ktorý emituje všetky položky emitované sourceObservable ktoré sú odlišné:

Pozorovateľný zdrojObservable = Observable .just (1, 1, 2, 2, 1, 3, 3, 1); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný differentObservable = sourceObservable.distinct (); differentObservable.subscribe (predplatiteľ); subscriber.assertValues ​​(1, 2, 3);

Ak však chceme získať Pozorovateľné ktorý emituje všetky položky emitované sourceObservable ktoré sa líšia od svojich bezprostredných predchodcov, môžeme použiť zreteľný, kým sa nezmení operátor:

Pozorovateľný zdrojObservable = Observable .just (1, 1, 2, 2, 1, 3, 3, 1); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľné differentObservable = sourceObservable.distinctUntilChanged (); differentObservable.subscribe (predplatiteľ); subscriber.assertValues ​​(1, 2, 1, 3, 1);

3.5. The ignoreElements Prevádzkovateľ

Kedykoľvek chceme ignorovať všetky prvky vyžarované sourceObservable, môžeme jednoducho použiť ignoreElements:

Pozorovateľný zdrojObservable = Pozorovateľný.rozsah (1, 10); Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľné ignoredObservable = sourceObservable.ignoreElements (); ignoredObservable.subscribe (predplatiteľ); subscriber.assertNoValues ​​();

4. Operátori filtrovania času

Pri práci s pozorovateľnou sekvenciou nie je časová os známa, niekedy však môže byť užitočné získať včasné údaje zo sekvencie.

Za týmto účelom RxJava ponúka niekoľko metód, ktoré nám umožňujú pracovať Pozorovateľné tiež pomocou časovej osi.

Predtým, ako prejdeme k prvému, definujme časovaný údaj Pozorovateľné ktorý vydá položku každú sekundu:

TestScheduler testScheduler = nový TestScheduler (); Observable timedObservable = Pozorovateľné .just (1, 2, 3, 4, 5, 6) .zipWith (Observable.interval (0, 1, TimeUnit.SECONDS, testScheduler), (item, time) -> item);

The TestScheduler je špeciálny plánovač, ktorý umožňuje ručný posun hodín akýmkoľvek tempom, ktoré uprednostňujeme.

4.1. vzorka a škrtiaca klapka Operátorov

The vzorka operátor filtruje timedObservable, vracajúci sa Pozorovateľné ktorá v časových intervaloch vydáva najnovšie položky emitované týmto rozhraním API.

Pozrime sa, ako môžeme vzorku timedObservable, filtrovanie iba poslednej emitovanej položky každé 2,5 sekundy:

Predplatiteľ TestSubscriber = nový TestSubscriber (); Observable sampledObservable = timedObservable .sample (2500L, TimeUnit.MILLISECONDS, testScheduler); sampledObservable.subscribe (predplatiteľ); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(3, 5, 6);

Tento druh správania sa dá dosiahnuť aj pomocou škrtiaca klapka operátor.

4.2. The plynPrvý Prevádzkovateľ

The plyn operátor sa líši od škrtiaca klapkaPosledná / vzorka pretože emituje prvú položku emitovanú timedObservable v každom období vzorkovania namiesto naposledy emitovaného.

Pozrime sa, ako môžeme emitovať prvé položky pomocou periódy vzorkovania 4 sekundy:

Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = timedObservable .throttleFirst (4100L, TimeUnit.SECONDS, testScheduler); filtrovanyobslužnýsubscribe (predplatiteľ); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(1, 6);

4.3. debounce a throttleWithTimeout Operátorov

Vďaka debounce operátor, je možné emitovať iba položku, ak uplynul konkrétny časový úsek bez emitovania ďalšej položky.

Preto, ak vyberieme časový interval, ktorý je väčší ako časový interval medzi emitovanými položkami čísla timedObservable, bude vydávať iba posledný. Na druhej strane, ak je menší, bude emitovať všetky položky emitované kódom timedObservable.

Pozrime sa, čo sa stane v prvom scenári:

Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = timedObservable .debounce (2000L, TimeUnit.MILLISECONDS, testScheduler); filtrovanyobslužnýsubscribe (predplatiteľ); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValue (6);

Tento druh správania sa dá dosiahnuť aj použitím throttleWithTimeout.

4.4. The čas vypršal Prevádzkovateľ

The čas vypršal operátor zrkadlí zdroj Pozorovateľné, ale vydá chybu oznámenia a preruší emisiu položiek, ak je zdrojom Pozorovateľné nedokáže počas určeného časového intervalu emitovať žiadne položky.

Pozrime sa, čo sa stane, ak zadáme časový limit 500 milisekúnd timedObservable:

Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = timedObservable .timeout (500L, TimeUnit.MILLISECONDS, testScheduler); filtrovanyobslužnýsubscribe (predplatiteľ); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertError (TimeoutException.class); subscriber.assertValues ​​(1);

5. Viacnásobné pozorovateľné filtrovanie

Pri práci s Pozorovateľné, je určite možné rozhodnúť sa, či sa majú položky filtrovať alebo preskakovať na základe sekundy Pozorovateľné.

Predtým, ako prejdeme ďalej, definujme a delayedObservable, ktorá po 3 sekundách vydá iba 1 položku:

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

Začnime s vziaťAž operátor.

5.1. The vziaťAž Prevádzkovateľ

The vziaťAž operátor zahodí všetky položky emitované zdrojom Pozorovateľné (timedObservable) po sekunde Pozorovateľné (delayedObservable) vydá položku alebo ukončí:

Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľný filterObservable = timedObservable .skipUntil (delayedObservable); filtrovanyobslužnýsubscribe (predplatiteľ); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(4, 5, 6);

5.2. The skipUntil Prevádzkovateľ

Na druhej strane, skipUntil zahodí všetky položky emitované zdrojom Pozorovateľné (timedObservable) do sekundy Pozorovateľné (delayedObservable) vydáva položku:

Predplatiteľ TestSubscriber = nový TestSubscriber (); Pozorovateľné filtrovanéObservovateľné = timedObservable .takeUntil (delayedObservable); filtrovanyobslužnýsubscribe (predplatiteľ); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(1, 2, 3);

6. Záver

V tomto rozsiahlom tutoriáli sme preskúmali rôzne operátory filtrovania dostupné v rámci RxJava, ktoré poskytujú jednoduchý príklad každého z nich.

Všetky príklady kódov v tomto článku nájdete ako vždy na GitHub.