סינון תצפיות ב- RxJava

1. הקדמה

בעקבות ההקדמה ל- RxJava, אנו נסתכל על מפעילי הסינון.

בפרט, אנו נתמקד בסינון, דילוג, סינון זמן וכמה פעולות סינון מתקדמות יותר.

2. סינון

כשעובדים עם נצפה, לפעמים כדאי לבחור רק קבוצת משנה של פריטים שנפלטים. למטרה זו, RxJava מציעה יכולות סינון שונות.

נתחיל להסתכל על ה- לְסַנֵן שיטה.

2.1. ה לְסַנֵן מַפעִיל

במילים פשוטות, ה לְסַנֵן מפעיל מסנן נצפה לוודא שהפריטים הנפלטים תואמים למצב שצוין, שמגיע בצורה של א לְבַסֵס.

בואו נראה כיצד נוכל לסנן רק את הערכים המוזרים מאלה שנפלטו:

מקור נצפהObservable = Observable.range (1, 10); מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = sourceObservable .filter (i -> i% 2! = 0); filteredObservable.subscribe (מנוי); subscriber.assertValues ​​(1, 3, 5, 7, 9);

2.2. ה לקחת מַפעִיל

כשמסננים עם לקחת, ההיגיון מביא לפליטת הראשון נ פריטים תוך התעלמות מהפריטים שנותרו.

בואו נראה איך נוכל לסנן את מָקוֹרנצפה ופולט רק את שני הפריטים הראשונים:

מקור נצפהObservable = Observable.range (1, 10); מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = sourceObservable.take (3); filteredObservable.subscribe (מנוי); subscriber.assertValues ​​(1, 2, 3);

2.3. ה קח תוך כדי מַפעִיל

כשמשתמש קח תוך כדי, המסוננים נצפה ימשיך לפלוט פריטים עד שייפגש עם אלמנט ראשון שאינו תואם את לְבַסֵס.

בואו נראה איך נוכל להשתמש ב- קח תוך כדי - עם סינון לְבַסֵס:

מקור נצפה Observable = Observable.just (1, 2, 3, 4, 3, 2, 1); מנוי TestSubscriber = חדש TestSubscriber (); תצפית מסוננתObservable = sourceObservable .takeWhile (i -> i <4); filteredObservable.subscribe (מנוי); subscriber.assertValues ​​(1, 2, 3);

2.4. ה קח ראשון מַפעִיל

בכל פעם שאנחנו רוצים להוציא רק את הפריט הראשון התואם לתנאי נתון, אנחנו יכולים להשתמש בו takeFirst ().

בואו נסתכל במהירות כיצד אנו יכולים לפלוט את הפריט הראשון שגודל יותר מ -5:

מקור נצפה Observable = Observable .just (1, 2, 3, 4, 5, 7, 6); מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = sourceObservable .takeFirst (x -> x> 5); filteredObservable.subscribe (מנוי); subscriber.assertValue (7);

2.5. ראשון ו firstOrDefault מפעילים

ניתן להשיג התנהגות דומה באמצעות ה- ראשון ממשק API:

מקור נצפהObservable = Observable.range (1, 10); מנוי TestSubscriber = חדש TestSubscriber (); תצפית מסוננתObservable = sourceObservable.first (); filteredObservable.subscribe (מנוי); subscriber.assertValue (1);

עם זאת, אם אנו רוצים לציין ערך ברירת מחדל, אם לא נפלטים פריטים, נוכל להשתמש בהם firstOrDefault:

מקור נצפהObservable = Observable.empty (); תצפית מסוננתObservable = sourceObservable.firstOrDefault (-1); filteredObservable.subscribe (מנוי); subscriber.assertValue (-1);

2.6. ה קח אחרון מַפעִיל

לאחר מכן, אם אנו רוצים לפלוט רק את האחרון נ פריטים הנפלטים על ידי נצפה, אנחנו יכולים להשתמש קח אחרון.

בואו נראה איך אפשר להוציא רק את שלושת הפריטים האחרונים:

מקור נצפהObservable = Observable.range (1, 10); מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = sourceObservable.takeLast (3); filteredObservable.subscribe (מנוי); subscriber.assertValues ​​(8, 9, 10);

עלינו לזכור שהדבר מעכב את פליטת פריט כלשהו מהמקור נצפה עד שהוא יושלם.

2.7. אחרון ו lastOrDefault

אם אנחנו רוצים לפלוט רק את האלמנט האחרון, אחר אז משתמשים takeLast (1), אנחנו יכולים להשתמש אחרון.

זה מסנן את נצפה, פולט רק את האלמנט האחרון, המאמת אופציונלי סינון לְבַסֵס:

מקור נצפהObservable = Observable.range (1, 10); מנוי TestSubscriber = חדש TestSubscriber (); נצפה מסונן Observable = sourceObservable. Last (i -> i% 2! = 0); filteredObservable.subscribe (מנוי); subscriber.assertValue (9);

למקרה ש נצפה הוא ריק, אנחנו יכולים להשתמש בו lastOrDefault, המסנן את נצפה פולטת את ערך ברירת המחדל.

ערך ברירת המחדל נפלט גם אם lastOrDefault נעשה שימוש במפעיל ואין פריטים המאמתים את מצב הסינון:

מקור נצפהObservable = Observable.range (1, 10); מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = sourceObservable.lastOrDefault (-1, i -> i> 10); filteredObservable.subscribe (מנוי); subscriber.assertValue (-1);

2.8. elementAt ו elementAtOrDefault מפעילים

עם ה elementAt אנו יכולים לבחור פריט יחיד שנפלט על ידי המקור נצפה, המציין את האינדקס שלו:

מקור נצפה Observable = Observable .just (1, 2, 3, 5, 7, 11); מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = sourceObservable.elementAt (4); filteredObservable.subscribe (מנוי); subscriber.assertValue (7);

למרות זאת, elementAt יזרוק IndexOutOfBoundException אם האינדקס שצוין עולה על מספר הפריטים שנפלטו.

כדי להימנע ממצב זה, ניתן להשתמש בו elementAtOrDefault - שיחזיר ערך ברירת מחדל במקרה שהאינדקס נמצא מחוץ לטווח:

מקור נצפה Observable = Observable .just (1, 2, 3, 5, 7, 11); מנוי TestSubscriber = חדש TestSubscriber (); תצפית מסוננתObservable = sourceObservable.elementAtOrDefault (7, -1); filteredObservable.subscribe (מנוי); subscriber.assertValue (-1);

2.9. ה ofType מַפעִיל

בכל פעם שה נצפה פולט לְהִתְנַגֵד פריטים, ניתן לסנן אותם על פי סוגם.

בואו נראה איך אנחנו יכולים רק לסנן את חוּט פריטי סוג שנפלטו:

Source ObservableObservable = Observable.just (1, "two", 3, "five", 7, 11); מנוי TestSubscriber = חדש TestSubscriber (); תצפית מסוננתObservable = sourceObservable.ofType (String.class); filteredObservable.subscribe (מנוי); subscriber.assertValues ​​("שניים", "חמש");

3. דילוג

מצד שני, כאשר אנו רוצים לסנן או לדלג על חלק מהפריטים הנפלטים על ידי נצפה, RxJava מציעה כמה מפעילים כמקבילה לסינונים, שדנו בעבר.

נתחיל להסתכל על ה- לדלג מפעיל, המקביל של לקחת.

3.1. ה לדלג מַפעִיל

כאשר an נצפה פולט רצף של פריטים, ניתן לסנן או לדלג על כמה מהפריטים הראשונים שהופלטו באמצעות לדלג.

לדוגמה. בואו נראה איך אפשר לדלג על ארבעת האלמנטים הראשונים:

מקור נצפהObservable = Observable.range (1, 10); מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = sourceObservable.skip (4); filteredObservable.subscribe (מנוי); subscriber.assertValues ​​(5, 6, 7, 8, 9, 10);

3.2. ה דלג תוך כדי מַפעִיל

בכל פעם שאנחנו רוצים לסנן את כל הערכים הראשונים שנפלטים על ידי נצפה שנכשלים בתנאי סינון נוכל להשתמש ב- דלג תוך כדי מַפעִיל:

מקור נצפה Observable = Observable .just (1, 2, 3, 4, 5, 4, 3, 2, 1); מנוי TestSubscriber = חדש TestSubscriber (); תצפית מסוננתObservable = sourceObservable .skipWhile (i -> i <4); filteredObservable.subscribe (מנוי); subscriber.assertValues ​​(4, 5, 4, 3, 2, 1);

3.3. ה skipLast מַפעִיל

ה skipLast המפעיל מאפשר לנו לדלג על הפריטים הסופיים שנפלטו על ידי נצפה לקבל רק את אלה שנפלטו לפניהם.

בעזרת זה נוכל, למשל, לדלג על חמשת הפריטים האחרונים:

מקור נצפהObservable = Observable.range (1, 10); מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = sourceObservable.skipLast (5); filteredObservable.subscribe (מנוי); subscriber.assertValues ​​(1, 2, 3, 4, 5);

3.4. מוּבהָק ו distinctUntilChanged מפעילים

ה מוּבהָק מפעיל מחזיר נצפה הפולט את כל הפריטים הנפלטים על ידי מקור נצפה הנבדלים:

מקור נצפה Observable = Observable .just (1, 1, 2, 2, 1, 3, 3, 1); מנוי TestSubscriber = חדש TestSubscriber (); מובחן נצפהObservable = sourceObservable.distinct (); distinctObservable.subscribe (מנוי); subscriber.assertValues ​​(1, 2, 3);

עם זאת, אם אנו רוצים להשיג נצפה הפולט את כל הפריטים הנפלטים על ידי מקור נצפה הנבדלים מקודם המיידי, אנו יכולים להשתמש ב- distinctUntilChanged מַפעִיל:

מקור נצפה Observable = Observable .just (1, 1, 2, 2, 1, 3, 3, 1); מנוי TestSubscriber = חדש TestSubscriber (); Observable distinctObservable = sourceObservable.distinctUntilChanged (); distinctObservable.subscribe (מנוי); subscriber.assertValues ​​(1, 2, 1, 3, 1);

3.5. ה להתעלם מאלמנטים מַפעִיל

בכל פעם שאנחנו רוצים להתעלם מכל האלמנטים הנפלטים על ידי מקור נצפהאנחנו יכולים פשוט להשתמש ב- ignoreElements:

מקור נצפהObservable = Observable.range (1, 10); מנוי TestSubscriber = חדש TestSubscriber (); IgnoredObservable = sourceObservable.ignoreElements () נצפה ignoredObservable.subscribe (מנוי); subscriber.assertNoValues ​​();

4. מפעילי סינון זמן

כשעובדים עם רצף נצפה, ציר הזמן אינו ידוע, אך לפעמים קבלת נתונים בזמן מרצף יכולה להיות שימושית.

במטרה זו, RxJava מציע כמה שיטות המאפשרות לנו לעבוד איתן נצפה תוך שימוש גם בציר הזמן.

לפני שנמשיך לראשון, בואו נגדיר זמן מתוזמן נצפה שיפלט פריט בכל שנייה:

TestScheduler testScheduler = TestScheduler חדש (); תצפית מתוזמנתObservable = נצפה .just (1, 2, 3, 4, 5, 6) .zipWith (Observable.interval (0, 1, TimeUnit.SECONDS, testScheduler), (פריט, זמן) -> פריט);

ה TestScheduler הוא מתזמן מיוחד המאפשר לקדם את השעון באופן ידני בכל קצב שנעדיף.

4.1. לִטעוֹם ו מצערת אחרונה מפעילים

ה לִטעוֹם המפעיל מסנן את מתוזמן נצפה, מחזיר נצפה הפולט את הפריטים האחרונים שנפלטו על ידי ממשק API זה במרווחי זמן.

בואו נראה איך נוכל לדגום את מתוזמן נצפה, מסנן רק את הפריט האחרון שנפלט כל 2.5 שניות:

מנוי TestSubscriber = חדש TestSubscriber (); מדגם נצפהObservable = timedObservable. מדגם (2500L, TimeUnit.MILLISECONDS, testScheduler); sampledObservable.subscribe (מנוי); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(3, 5, 6);

סוג זה של התנהגות ניתן להשיג גם באמצעות מצערת אחרונה מַפעִיל.

4.2. ה מצערת ראשונה מַפעִיל

ה מצערת ראשונה מפעיל שונה מ מצערת אחרון / מדגם מכיוון שהוא פולט את הפריט הראשון שנפלט על ידי מתוזמן נצפה בכל תקופת דגימה במקום האחרונה שנפלטה.

בואו נראה כיצד אנו יכולים לפלוט את הפריטים הראשונים, תוך שימוש בתקופת דגימה של 4 שניות:

מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = מתוזמןObservable .throttleFirst (4100L, TimeUnit.SECONDS, testScheduler); filteredObservable.subscribe (מנוי); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(1, 6);

4.3. להקפיץ ו מצערת ללא זמן מפעילים

עם ה להקפיץ אופרטור, ניתן לפלוט רק פריט אם עבר זמן מסוים מבלי להוציא פריט אחר.

לכן, אם אנו בוחרים פרק זמן גדול יותר מרווח הזמן בין הפריטים הנפלטים של ה- מתוזמן נצפה, זה רק יפלט את האחרון. מצד שני, אם הוא קטן יותר, הוא יפלוט את כל הפריטים שנפלטים על ידי מתוזמן נצפה.

בואו נראה מה קורה בתרחיש הראשון:

מנוי TestSubscriber = חדש TestSubscriber (); FiledObservable = timedObservable .debounce נצפה (2000L, TimeUnit.MILLISECONDS, testScheduler); filteredObservable.subscribe (מנוי); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValue (6);

סוג זה של התנהגות ניתן להשיג גם באמצעות מצערת ללא זמן.

4.4. ה פסק זמן מַפעִיל

ה פסק זמן מפעיל משקף את המקור נצפה, אך הוצא שגיאת הודעה, ובטל את פליטת הפריטים, אם המקור נצפה נכשל בפליטת פריטים במהלך פרק זמן מוגדר.

בואו נראה מה יקרה אם נציין פסק זמן של 500 אלפיות השנייה מתוזמן נצפה:

מנוי TestSubscriber = חדש TestSubscriber (); תצפית מסוננתObservable = timeedObservable. Timeout (500L, TimeUnit.MILLISECONDS, testScheduler); filteredObservable.subscribe (מנוי); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertError (TimeoutException.class); subscriber.assertValues ​​(1);

5. סינון מרובה נצפה

כשעובדים עם נצפהבהחלט ניתן להחליט אם סינון או דילוג על פריטים על סמך שנייה נצפה.

לפני שנמשיך, בואו נגדיר א מושהה נצפה, שייפלט פריט אחד בלבד לאחר 3 שניות:

נצפה מאוחרObservable = Observable.just (1). Delay (3, TimeUnit.SECONDS, testScheduler);

בוא נתחיל עם קח עד מַפעִיל.

5.1. ה קח עד מַפעִיל

ה קח עד המפעיל משליך כל פריט שנפלט על ידי המקור נצפה (מתוזמן נצפה) אחרי שנייה נצפה (מושהה נצפה) פולט פריט או מסתיים:

מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = מתוזמןObservable .skipUntil (עיכובObservable); filteredObservable.subscribe (מנוי); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(4, 5, 6);

5.2. ה דלג עד מַפעִיל

מצד שני, דלג עד משליך כל פריט שנפלט על ידי המקור נצפה (מתוזמן נצפה) עד שנייה נצפה (מושהה נצפה) פולט פריט:

מנוי TestSubscriber = חדש TestSubscriber (); סינון נצפהObservable = מתוזמןObservable .takeUntil (עיכובObservable); filteredObservable.subscribe (מנוי); testScheduler.advanceTimeBy (7, TimeUnit.SECONDS); subscriber.assertValues ​​(1, 2, 3);

6. מסקנה

במדריך נרחב זה בחנו את מפעילי הסינון השונים הזמינים ב- RxJava, ומספקים דוגמה פשוטה לכל אחד מהם.

כמו תמיד, ניתן למצוא את כל דוגמאות הקוד במאמר זה ב- GitHub.


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