אתם יכולים להשתמש בספריות המועדפות שלכם ב-Compose. בקטע הזה נסביר איך לשלב כמה מהספריות הכי שימושיות.
פעילות
כדי להשתמש ב-Compose בפעילות, צריך להשתמש ב-ComponentActivity, שהוא מחלקת משנה של Activity שמספקת את LifecycleOwner המתאים ואת הרכיבים ל-Compose. הוא מספק גם ממשקי API נוספים שמפרידים את הקוד שלכם משיטות דריסה במחלקת הפעילות.
Activity Compose חושף את ממשקי ה-API האלה לפונקציות Composable, כך שלא נדרש יותר להחליף שיטות מחוץ לפונקציות Composable או לאחזר מופע Activity מפורש.
בנוסף, ממשקי ה-API האלה מוודאים שהם מאותחלים רק פעם אחת, שהם שורדים את ההרכבה מחדש ושהם מנקים את עצמם בצורה תקינה אם רכיב ה-Composable מוסר מההרכב.
תוצאת הפעילות
rememberLauncherForActivityResult() API מאפשר לכם לקבל תוצאה מפעילות בקומפוזיציה:
@Composable fun GetContentExample() { var imageUri by remember { mutableStateOf<Uri?>(null) } val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> imageUri = uri } Column { Button(onClick = { launcher.launch("image/*") }) { Text(text = "Load Image") } Image( painter = rememberAsyncImagePainter(imageUri), contentDescription = "My Image" ) } }
בדוגמה הזו מוצג חוזה פשוט של GetContent(). הקשה על הלחצן מפעילה את הבקשה. ה-lambda האחורי של
rememberLauncherForActivityResult()
מופעל ברגע שהמשתמש בוחר תמונה וחוזר לפעילות ההפעלה.
התמונה שנבחרה נטענת באמצעות הפונקציה rememberImagePainter() של Coil.
אפשר להשתמש בכל מחלקת משנה של ActivityResultContract כארגומנט הראשון של rememberLauncherForActivityResult().
המשמעות היא שאפשר להשתמש בטכניקה הזו כדי לבקש תוכן מהמסגרת וגם בדפוסים נפוצים אחרים. אפשר גם ליצור חוזים מותאמים אישית ולהשתמש בהם בטכניקה הזו.
שליחת בקשה להרשאות בזמן ריצה
אפשר להשתמש באותו API של תוצאות פעילות ובאותו חוזה rememberLauncherForActivityResult() שמוסברים למעלה כדי לבקש הרשאות בזמן ריצה באמצעות חוזה RequestPermission להרשאה יחידה או חוזה RequestMultiplePermissions לכמה הרשאות.
אפשר גם להשתמש בספריית ההרשאות של Accompanist כשכבה מעל ממשקי ה-API האלה כדי למפות את המצב הנוכחי של ההרשאות למצב שבו ממשק המשתמש של Compose יכול להשתמש.
טיפול בכפתור 'הקודם' במערכת
כדי לספק ניווט לאחור מותאם אישית ולשנות את פעולת ברירת המחדל של הכפתור "הקודם" של המערכת מתוך הפונקציה הקומפוזבילית, הפונקציה הקומפוזבילית יכולה להשתמש ב-BackHandler כדי ליירט את האירוע הזה:
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
הארגומנט הראשון קובע אם BackHandler מופעל כרגע. אפשר להשתמש בארגומנט הזה כדי להשבית באופן זמני את ה-handler בהתאם למצב הרכיב. פונקציית ה-lambda האחרונה תופעל אם המשתמש יפעיל אירוע חזרה למערכת, ו-BackHandler מופעל כרגע.
ViewModel
אם משתמשים בספרייה Architecture Components ViewModel, אפשר לגשת אל ViewModel מכל פונקציה שניתנת להרכבה על ידי קריאה לפונקציה viewModel(). מוסיפים את יחסי התלות הבאים לקובץ Gradle:
מגניב
dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0' }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0") }
אחר כך תוכלו להשתמש בפונקציה viewModel() בקוד.
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { // use viewModel here }
viewModel() מחזירה ViewModel קיים או יוצרת אחד חדש. כברירת מחדל, הערך ViewModel שמוחזר מוגבל לפעילות, לקטע או ליעד הניווט שמכילים אותו, והוא נשמר כל עוד ההיקף פעיל.
לדוגמה, אם הקומפוזיציה נמצאת בשימוש בפעילות, viewModel() מחזירה את אותו מופע עד שהפעילות מסתיימת או שהתהליך מופסק.
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( // Returns the same instance as long as the activity is alive, // just as if you grabbed the instance from an Activity or Fragment viewModel: MyViewModel = viewModel() ) { /* ... */ } @Composable fun MyScreen2( viewModel: MyViewModel = viewModel() // Same instance as in MyScreen ) { /* ... */ }
הנחיות שימוש
בדרך כלל ניגשים למופעים של ViewModel ברכיבים קומפוזביליים ברמת המסך, כלומר קרוב לרכיב קומפוזבילי בסיסי שנקרא מפעילות, ממקטע או מיעד של תרשים ניווט. הסיבה לכך היא ש-ViewModels מוגדרים כברירת מחדל בהיקף של האובייקטים האלה ברמת המסך. מידע נוסף על מחזור החיים וההיקף של ViewModel
מומלץ להימנע מהעברה של מופעי ViewModel לרכיבי Composable אחרים, כי זה יכול להקשות על הבדיקה של רכיבי Composable האלה ולגרום לשיבוש תצוגות מקדימות. במקום זאת, מעבירים רק את הנתונים והפונקציות שהם צריכים כפרמטרים.
אפשר להשתמש במופעים של ViewModel כדי לנהל את המצב של קומפוזיציות ברמת מסך המשנה, אבל חשוב להכיר את מחזור החיים וההיקף של ViewModel. אם רכיב ה-Composable הוא עצמאי, כדאי להשתמש ב-Hilt כדי להוסיף את ViewModel, וכך לא תצטרכו להעביר תלויות מרכיבי ה-Composable של ההורה.
אם למדד ViewModel יש תלויות, הפונקציה viewModel() מקבלת כפרמטר את ViewModelProvider.Factory האופציונלי.
מידע נוסף על ViewModel בכתיבה ועל אופן השימוש במופעים עם ספריית הניווט בכתיבה, או פעילויות וקטעים, זמין במסמכי יכולת הפעולה ההדדית.
מקורות נתונים
Compose כולל תוספים לפתרונות הפופולריים ביותר של Android שמבוססים על סטרימינג. כל אחד מהתוספים האלה מסופק על ידי ארטיפקט אחר:
-
LiveData.observeAsState()כלול בפריט המידע שנוצר בתהליך פיתוח (Artifact)androidx.compose.runtime:runtime-livedata:$composeVersion. Flow.collectAsState()לא דורש תלות נוספת.-
Observable.subscribeAsState()כלול בפריט המידע שנוצר בתהליך פיתוח (Artifact)androidx.compose.runtime:runtime-rxjava2:$composeVersionאוandroidx.compose.runtime:runtime-rxjava3:$composeVersion.
הארטיפקטים האלה נרשמים כמאזינים ומייצגים את הערכים כ-State. בכל פעם שמופק ערך חדש, Compose מבצעת קומפוזיציה מחדש של אותם חלקים בממשק המשתמש שבהם נעשה שימוש ב-state.value. לדוגמה, בקוד הזה, ShowData מורכב מחדש בכל פעם
ש-exampleLiveData פולט ערך חדש.
// import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { val dataExample = viewModel.exampleLiveData.observeAsState() // Because the state is read here, // MyScreen recomposes whenever dataExample changes. dataExample.value?.let { ShowData(dataExample) } }
פעולות אסינכרוניות בפיתוח נייטיב
Jetpack Compose מאפשר לכם להריץ פעולות אסינכרוניות באמצעות שגרות המשך (coroutine) מתוך רכיבים קומפוזביליים.
מידע נוסף זמין במאמר תיעוד בנושא תופעות לוואי על ממשקי ה-API LaunchedEffect, produceState ו-rememberCoroutineScope.
ניווט
רכיב הניווט מספק תמיכה באפליקציות Jetpack Compose. מידע נוסף זמין במאמרים ניווט באמצעות Compose והעברת נתונים מ-Jetpack Navigation ל-Navigation Compose.
Hilt
Hilt הוא הפתרון המומלץ להזרקת תלות באפליקציות ל-Android, והוא פועל בצורה חלקה עם Compose.
הפונקציה viewModel() שמוזכרת בקטע ViewModel משתמשת באופן אוטומטי ב-ViewModel ש-Hilt בונה באמצעות ההערה @HiltViewModel. סיפקנו מסמכי תיעוד עם מידע על שילוב של ViewModel ב-Hilt.
@HiltViewModel class MyViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, private val repository: ExampleRepository ) : ViewModel() { /* ... */ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { /* ... */ }
Hilt ו-Navigation
Hilt משתלב גם עם ספריית Navigation Compose. מוסיפים את יחסי התלות הנוספים הבאים לקובץ Gradle:
מגניב
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.3.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.3.0") }
כשמשתמשים ב-Navigation Compose, תמיד צריך להשתמש בפונקציה הקומפוזבילית hiltViewModel כדי לקבל מופע של @HiltViewModel עם ההערה ViewModel.
התכונה הזו פועלת עם קטעי קוד או פעילויות שמוערים באמצעות התג @AndroidEntryPoint.
לדוגמה, אם ExampleScreen הוא יעד בתרשים ניווט, צריך לקרוא ל-hiltViewModel() כדי לקבל מופע של ExampleViewModel בהיקף של היעד, כמו שמוצג בקטע הקוד הבא:
// import androidx.hilt.navigation.compose.hiltViewModel @Composable fun MyApp() { val navController = rememberNavController() val startRoute = "example" NavHost(navController, startDestination = startRoute) { composable("example") { backStackEntry -> // Creates a ViewModel from the current BackStackEntry // Available in the androidx.hilt:hilt-navigation-compose artifact val viewModel = hiltViewModel<MyViewModel>() MyScreen(viewModel) } /* ... */ } }
אם אתם צריכים לאחזר את המופע של ViewModel בהיקף של נתיבי ניווט או גרף הניווט, במקום זאת, השתמשו בפונקציה קומפוזבילית hiltViewModel והעבירו את backStackEntry המתאים כפרמטר:
// import androidx.hilt.navigation.compose.hiltViewModel // import androidx.navigation.compose.getBackStackEntry @Composable fun MyApp() { val navController = rememberNavController() val startRoute = "example" val innerStartRoute = "exampleWithRoute" NavHost(navController, startDestination = startRoute) { navigation(startDestination = innerStartRoute, route = "Parent") { // ... composable("exampleWithRoute") { backStackEntry -> val parentEntry = remember(backStackEntry) { navController.getBackStackEntry("Parent") } val parentViewModel = hiltViewModel<ParentViewModel>(parentEntry) ExampleWithRouteScreen(parentViewModel) } } } }
חלוקה לדפים
ספריית ההחלפה לדפים מאפשרת לכם לטעון נתונים בהדרגה, והיא נתמכת ב-Compose.
בדף המידע על הגרסה של Paging מפורטות התלות הנוספת ב-paging-compose שצריך להוסיף לפרויקט ולגרסה שלו.
דוגמה לממשקי ה-API של Compose בספריית Paging:
@Composable fun MyScreen(flow: Flow<PagingData<String>>) { val lazyPagingItems = flow.collectAsLazyPagingItems() LazyColumn { items( lazyPagingItems.itemCount, key = lazyPagingItems.itemKey { it } ) { index -> val item = lazyPagingItems[index] Text("Item is $item") } } }
מידע נוסף על שימוש בהחלפה בין דפים ב-Compose זמין במסמכי התיעוד בנושא רשימות ורשתות.
מפות
אפשר להשתמש בספריית Maps Compose כדי לספק את מפות Google באפליקציה. הנה דוגמה לשימוש:
@Composable fun MapsExample() { val singapore = LatLng(1.35, 103.87) val cameraPositionState = rememberCameraPositionState { position = CameraPosition.fromLatLngZoom(singapore, 10f) } GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState ) { Marker( state = remember { MarkerState(position = singapore) }, title = "Singapore", snippet = "Marker in Singapore" ) } }
מומלץ בשבילך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- תופעות לוואי בפיתוח נייטיב
- מצב ו-Jetpack פיתוח נייטיב
- שמירת מצב ממשק המשתמש בפיתוח נייטיב