באמצעות Navigation Compose API אפשר לנווט בין רכיבים ב-Compose באפליקציה, תוך ניצול התשתית, הרכיבים והתכונות של Jetpack Navigation.
בדף הזה מוסבר איך לעבור מ-Jetpack Navigation שמבוסס על קטעים (fragments) ל-Navigation Compose, כחלק מהמעבר המקיף יותר מממשק משתמש שמבוסס על תצוגות (views) ל-Jetpack Compose.
תנאים מוקדמים להעברה
תוכלו לעבור ל-Navigation Compose אחרי שתוכלו להחליף את כל ה-Fragments ברכיבי Compose של המסך המתאימים. רכיבים מותאמים אישית במסך יכולים להכיל שילוב של תוכן מ-Compose ותוכן מ-View, אבל כל יעדי הניווט חייבים להיות רכיבים מותאמים אישית כדי לאפשר העברה של Compose לניווט. עד אז, כדאי להמשיך להשתמש ברכיב הניווט שמבוסס על קטעי קוד בקוד הבסיס של View ו-Compose לצורך יכולת פעולה הדדית. למידע נוסף, עיינו במסמכי התיעוד בנושא יכולת פעולה הדדית של ניווט.
אין צורך להשתמש בתכונה 'ניווט ב-Compose' באפליקציה של Compose בלבד. תוכלו להמשיך להשתמש ברכיב הניווט שמבוסס על קטעי קוד, כל עוד תמשיכו להשתמש בקטעי הקוד לאירוח התוכן הניתן ליצירה.
שלבי ההעברה
בין שאתם פועלים לפי אסטרטגיית ההעברה המומלצת שלנו ובין שאתם משתמשים בגישה אחרת, תגיעו לשלב שבו כל יעדי הניווט יהיו רכיבים שניתנים ליצירה במסך, ורכיבי ה-Fragment ישמשו רק כקונטיינרים ליצירה. בשלב הזה תוכלו לעבור לכתיבה באמצעות ניווט.
אם האפליקציה שלכם כבר עומדת בתבנית העיצוב של UDF ובמדריך שלנו לארכיטקטורה, המעבר ל-Jetpack Compose ול-Navigation Compose לא אמור לחייב שינויים משמעותיים בשכבות אחרות של האפליקציה, מלבד שכבת ממשק המשתמש.
כדי לעבור ל'כתיבה עם ניווט':
- מוסיפים לאפליקציה את התלות ב-Navigation Compose.
יוצרים רכיב
App-level
ו מוסיפים אותו ל-Activity
בתור נקודת הכניסה ל-Compose, ומחליפים את ההגדרה של פריסת התצוגה:class SampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // setContentView<ActivitySampleBinding>(this, R.layout.activity_sample) setContent { SampleApp(/* ... */) } } }
יוצרים סוגים לכל יעד ניווט. משתמשים ב-
data object
ליעדים שלא דורשים נתונים, וב-data class
או ב-class
ליעדים שדורשים נתונים.@Serializable data object First @Serializable data class Second(val id: String) @Serializable data object Third
מגדירים את
NavController
במקום שבו לכל הרכיבים הניתנים לשילוב שצריכים להפנות אליו יש גישה (בדרך כלל בתוך הרכיב הניתן לשילובApp
). הגישה הזו מבוססת על העקרונות של העלאת המצב ומאפשרת להשתמש ב-NavController
כמקור האמיתי לניווט בין המסכים הניתנים ליצירה ולתחזוקה של סטאק העורפי:@Composable fun SampleApp() { val navController = rememberNavController() // ... }
יוצרים את
NavHost
של האפליקציה בתוך ה-composable שלApp
ומעבירים אתnavController
:@Composable fun SampleApp() { val navController = rememberNavController() SampleNavHost(navController = navController) } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { // ... } }
מוסיפים את היעדים
composable
כדי ליצור את תרשים הניווט. אם כל המסכים הועברו בעבר ל-Compose, השלב הזה כולל רק חילוץ של רכיבי ה-Compose של המסכים מה-Fragments ליעדיםcomposable
:class FirstFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { return ComposeView(requireContext()).apply { setContent { // FirstScreen(...) EXTRACT FROM HERE } } } } @Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen(/* ... */) // EXTRACT TO HERE } composable<Second> { SecondScreen(/* ... */) } // ... } }
אם פעלתם לפי ההנחיות לתכנון ממשק המשתמש של Compose, ובמיוחד לפי ההנחיות לגבי העברת
ViewModel
ואירועי ניווט לרכיבי Compose, השלב הבא הוא לשנות את האופן שבו אתם מספקים אתViewModel
לכל רכיב Compose במסך. לעיתים קרובות אפשר להשתמש בהזרקה של Hilt ובנקודת השילוב שלה עם Compose ו-Navigation באמצעותhiltViewModel
:@Composable fun FirstScreen( // viewModel: FirstViewModel = viewModel(), viewModel: FirstViewModel = hiltViewModel(), onButtonClick: () -> Unit = {}, ) { // ... }
מחליפים את כל קריאות הניווט של
findNavController()
בקריאות שלnavController
ומעבירים אותן כאירועי ניווט לכל מסך שאפשר ליצור, במקום להעביר אתnavController
כולו. הגישה הזו תואמת לשיטות המומלצות לחשיפת אירועים מפונקציות מורכבות למבצעי הקריאה, ומאפשרת לשמור עלnavController
כמקור המידע המהימן היחיד.כדי להעביר נתונים ליעד, יוצרים מופע של סוג המסלול שהוגדר ליעד הזה. לאחר מכן אפשר לקבל אותו ישירות מהרשומה ב-back stack ביעד, או מ-
ViewModel
באמצעותSavedStateHandle.toRoute()
.@Composable fun SampleNavHost( navController: NavHostController ) { NavHost(navController = navController, startDestination = First) { composable<First> { FirstScreen( onButtonClick = { // findNavController().navigate(firstScreenToSecondScreenAction) navController.navigate(Second(id = "ABC")) } ) } composable<Second> { backStackEntry -> val secondRoute = backStackEntry.toRoute<Second>() SecondScreen( id = secondRoute.id, onIconClick = { // findNavController().navigate(secondScreenToThirdScreenAction) navController.navigate(Third) } ) } // ... } }
מסירים את כל ה-Fragments, את הפריסות הרלוונטיות של ה-XML, את הניווט הלא הכרחי ואת המשאבים האחרים, ואת יחסי התלות הלא תקינים של Fragment ו-Jetpack Navigation.
אותם שלבים עם פרטים נוספים שקשורים ל-Navigation Compose מפורטים במסמכי ההגדרה.
תרחישים נפוצים לדוגמה
לא משנה באיזה רכיב ניווט אתם משתמשים, אותם עקרונות של ניווט חלים.
תרחישים נפוצים לדוגמה במהלך ההעברה:
- ניווט לרכיב שאפשר לשלב
- ניווט באמצעות ארגומנטים
- קישורי עומק
- ניווט בתצוגת עץ
- שילוב עם סרגל הניווט התחתון
- שילוב עם רכיב ניווט מותאם אישית
מידע מפורט יותר על תרחישי השימוש האלה זמין במאמר ניווט באמצעות Compose.
אחזור נתונים מורכבים בזמן הניווט
מומלץ מאוד לא להעביר אובייקטים מורכבים של נתונים במהלך הניווט. במקום זאת, מעבירים את המידע הנדרש המינימלי, כמו מזהה ייחודי או סוג אחר של מזהה, כארגומנטים כשמבצעים פעולות ניווט. מומלץ לאחסן אובייקטים מורכבים כנתונים במקור אחד לאמת, כמו שכבת הנתונים. מידע נוסף זמין במאמר אחזור נתונים מורכבים במהלך ניווט.
אם ה-Fragments מעבירים אובייקטים מורכבים כארגומנטים, מומלץ קודם לבצע רפאקציה של הקוד כך שיאפשר לאחסן את האובייקטים האלה בשכבת הנתונים ולאחזר אותם משם. דוגמאות זמינות במאמר Now in Android repository.
מגבלות
בקטע הזה מתוארות המגבלות הנוכחיות של 'כתיבה בזמן ניווט'.
העברה מצטברת ל-Navigation Compose
בשלב הזה אי אפשר להשתמש ב-Navigation Compose תוך שימוש ב-Fragments כיעדים בקוד. כדי להתחיל להשתמש בתכונה 'כתיבה של מסלול ניווט', כל היעדים צריכים להיות רכיבים שאפשר לשלב. אפשר לעקוב אחרי בקשת התכונה הזו במערכת למעקב אחר בעיות.
אנימציות מעבר
החל מ-Navigation 2.7.0-alpha01, יש תמיכה ישירה ב-NavHost
בהגדרת מעברים מותאמים אישית, שהיו זמינים בעבר ב-AnimatedNavHost
. מידע נוסף זמין בהערות המוצר.
מידע נוסף
למידע נוסף על המעבר ל-Navigation Compose, אפשר לעיין במקורות המידע הבאים:
- codelab של Navigation Compose: הדרכה מעשית ב-codelab על היסודות של Navigation Compose.
- עכשיו במאגר של Android: אפליקציית Android פונקציונלית לחלוטין שנוצרה כולה באמצעות Kotlin ו-Jetpack Compose, ועומדת בשיטות המומלצות של Android לעיצוב ולפיתוח, כולל Navigation Compose.
- העברת Sunflower ל-Jetpack Compose: פוסט בבלוג שמתעד את תהליך ההעברה של אפליקציית הדוגמה Sunflower מ-Views ל-Compose, כולל העברה ל-Navigation Compose.
- Jetnews לכל מסך: פוסט בבלוג שמתעד את תהליך ה-refactor וההעברה של קוד הדוגמה של Jetnews כך שיתמוך בכל המסכים באמצעות Jetpack Compose ו-Navigation Compose.
מומלץ עבורך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- ניווט באמצעות Compose
- Compose וספריות אחרות
- שיקולים נוספים