החלת לוגיקה או עטיפות על יעדים

אפשר לספק מידע נוסף או להחיל את אותו היגיון על יעדים באמצעות המחלקה NavEntryDecorator. המחלקה הזו עוטפת כל NavEntry במקבץ פעילויות קודמות (back stack) באמצעות פונקציה קומפוזבילית. במילים אחרות, הוא מעטר את התוכן של הרשומה.

יצירת מעצב בהתאמה אישית

כדי ליצור מעצב, מרחיבים את המחלקה NavEntryDecorator ומבטלים את השיטות הבאות:

  • ‫decorate – פונקציית lambda קומפוזבילית שנקראת לכל NavEntry במקבץ הפעילויות הקודמות (back stack). הוא מקבל את NavEntry כפרמטר. כך אפשר ליצור אובייקטים של מצב שמוצמדים ל-contentKey של הרשומה. אפשר להשתמש ב-CompositionLocalProvider כדי לספק יחסי תלות לתוכן של הרשומה. אפשר גם להקיף את התוכן בפונקציה קומפוזבילית או להפעיל תופעות לוואי. תמיד צריך להפעיל את entry.Content() בתוך ה-method הזו.
  • ‫onPop – קריאה חוזרת (callback) שמופעלת כש-NavEntry הוסר ממקבץ הפעילויות הקודמות (back stack) ויצא מהקומפוזיציה. הוא מקבל את הערך של contentKey מהרשומה שהוסרה. משתמשים ב-contentKey כדי לזהות ולנקות את כל המצבים שמשויכים לרשומה הזו.

בדוגמה הבאה, המחלקה NavEntryDecorator מורחבת כדי ליצור מעצב בהתאמה אישית.

// import androidx.navigation3.runtime.NavEntryDecorator
class CustomNavEntryDecorator<T : Any> : NavEntryDecorator<T>(
    decorate = { entry ->
        Log.d("CustomNavEntryDecorator", "entry with ${entry.contentKey} entered composition and was decorated")
        entry.Content()
    },
    onPop = { contentKey -> Log.d("CustomNavEntryDecorator", "entry with $contentKey was popped") }
)

אם ה-decorator צריך גישה למצב, יוצרים פונקציה קומפוזבילית שיוצרת את המצב הזה, ואז משתמשים בה כדי ליצור את ה-decorator. כדי לראות דוגמה להטמעה, עיינו בקוד המקור של rememberSaveableStateHolderNavEntryDecorator. כך נוצר המצב – SaveableStateHolder – ומשתמשים בו כדי ליצור את ה-decorator.

קישוט של מקבץ פעילויות קודמות (back stack)

אחרי שיוצרים את NavEntryDecorator, אפשר להוסיף רכיבים לרשומות במקבץ הפעילויות הקודמות באחת משתי דרכים:

  • משתמשים ב-rememberDecoratedNavEntries. הפונקציה הזו שימושית כשיש כמה מקבצי פעילויות קודמות, ולכל אחד מהם יש קבוצה משלו של מעצבים (לפרטים נוספים, ראו את המתכון הזה לקוד). הפונקציה מחזירה רשימה מעוטרת של NavEntry שאפשר להשתמש בה עם NavDisplay.
  • מזינים את ה-decorator ישירות ל-NavDisplay באמצעות הפרמטר entryDecorators. הפונקציה NavDisplay מפעילה את rememberDecoratedNavEntries מאחורי הקלעים ומציגה את הרשומות המעוטרות.

הכללת ה-decorator שמוגדר כברירת מחדל

‫Navigation 3 כולל מעצב ברירת מחדל בשם SaveableStateHolderNavEntryDecorator שמאפשר לשמור את המצב של NavEntry במהלך שינויים בהגדרות והשבתת תהליכים. הוא עוטף את התוכן של NavEntry ב-SaveableStateProvider, וכך מאפשר לקריאות של rememberSaveable בתוך התוכן של NavEntry לפעול כמו שצריך.

אם ה-decorator שלכם לא מספק SaveableStateProvider, צריך לכלול את SaveableStateHolderNavEntryDecorator בתור ה-decorator הראשון ברשימת ה-decorators שסופקו. הוא נוצר באמצעות rememberSaveableStateHolderNavEntryDecorator.

לדוגמה:

// import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
NavDisplay(
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        remember { CustomNavEntryDecorator() }
    ),
    // ...
)

העברת תוצאות באמצעות ResultEventBusNavEntryDecorator

החל מגרסה 1.2.0 של Navigation 3, אפשר להשתמש ב-ResultEventBusNavEntryDecorator כדי לספק ResultEventBus לכל NavEntry באמצעות ה-composition local‏ LocalResultEventBus.

כברירת מחדל, rememberResultEventBusNavEntryDecorator יוצר וזוכר מופע ResultEventBus משלו באופן פנימי באמצעות rememberResultEventBus. אם אתם צריכים לגשת לאוטובוס האירועים מחוץ להיררכיית ה-decorator (למשל, בפיגום של האפליקציה ברמה העליונה), אתם יכולים להרים את ResultEventBus על ידי קריאה ל-rememberResultEventBus והעברתו ל-rememberResultEventBusNavEntryDecorator(resultEventBus):

val resultEventBus = rememberResultEventBus()

NavDisplay(
    /* ... */
    entryDecorators = listOf(
        rememberSaveableStateHolderNavEntryDecorator(),
        rememberResultEventBusNavEntryDecorator(resultEventBus = resultEventBus)
    )
)

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

מתי כדאי להשתמש ב-decorator

אפשר להשתמש ב-decorator כדי:

  • צריך ליצור תלות לכל NavEntry במקבץ פעילויות קודמות (back stack). לדוגמה, ViewModelStoreNavEntryDecorator יוצר ViewModelStore לכל NavEntry.
  • העברת תוצאות ותקשורת בין יעדים. לדוגמה, ResultEventBusNavEntryDecorator מספק ResultEventBus ליעדים במקבץ הפעילויות הקודמות (back stack).
  • הגדרת היקף של אובייקט לכמה NavEntry. לדוגמה, כדי לשתף ViewModel בין כמה רשומות.
  • לבצע את אותה פעולה בכמה NavEntry. לדוגמה, כדי לבצע פעולות רישום ביומן, ניפוי באגים או מעקב לכל רשומה.
  • עוטפים את NavEntry באותה פונקציה קומפוזבילית.
  • ניקוי המצב שמשויך ל-NavEntry. לדוגמה, כשערך מוסר ממקבץ הפעילויות הקודמות (back stack), ה-ViewModelStoreNavEntryDecorator מנקה את ה-ViewModelStore שמשויך אליו.

אל תשתמשו במעטר כדי:

  • העברת תלות ל-NavEntry יחיד.
  • לספק יחסי תלות שההיקף שלהם רחב יותר ממקבץ הפעילויות הקודמות.

בשני המקרים האלה, צריך להעביר את התלות ישירות כשיוצרים את ה-NavEntry.

דוגמאות קוד נוספות זמינות ב-NavEntryDecorator.