אתם יכולים להשתמש בספריות המועדפות עליכם בכתיבה. בקטע הזה מוסבר איך לשלב כמה מהספריות הכי שימושיות.
פעילות
כדי להשתמש ב-Compose בפעילות, צריך להשתמש ב-ComponentActivity
, שהוא מחלקה משנית של Activity
שמספקת את LifecycleOwner
והרכיבים המתאימים ל-Compose. בנוסף, הוא מספק ממשקי API נוספים שמפרידים את הקוד שלכם משיטות דריסה במחלקת הפעילות.
Activity Compose חושף את ממשקי ה-API האלה לפונקציות Composable, כך שלא נדרש יותר לבטל שיטות מחוץ לפונקציות Composable או לאחזר מופע Activity
מפורש.
בנוסף, ממשקי ה-API האלה מוודאים שהם מאותחלים רק פעם אחת, שהם שורדים את ההרכבה מחדש ושהם מנקים את עצמם בצורה תקינה אם רכיב ה-Composable מוסר מההרכבה.
תוצאת פעילות
API
rememberLauncherForActivityResult()
מאפשר לכם
לקבל תוצאה מפעילות
ב-Composable:
@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 Permissions library כשכבה מעל ממשקי ה-API האלה כדי למפות את מצב ההרשאות הנוכחי למצב שבו ממשק המשתמש של Compose יכול להשתמש.
טיפול בכפתור 'הקודם' במערכת
כדי לספק ניווט מותאם אישית אחורה ולשנות את התנהגות ברירת המחדל של לחצן החזרה של המערכת מתוך רכיב ה-Composable, רכיב ה-Composable יכול להשתמש ב-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.8.5' }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5") }
אחר כך תוכלו להשתמש בפונקציה 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
בפריטים הניתנים להרכבה ברמת המסך, כלומר קרוב לפריט שניתן להרכבה ברמת הבסיס שנקרא מפעילות, מקטע או יעד של תרשים ניווט. הסיבה לכך היא שViewModel
s מוגדרים כברירת מחדל לטווח של האובייקטים האלה ברמת המסך. מידע נוסף על מחזור החיים וההיקף של ViewModel
כדאי להימנע מהעברה של מופעים של ViewModel
לרכיבי Composable אחרים, כי זה יכול להקשות על הבדיקה של רכיבי Composable האלה ולגרום לשיבוש בתצוגות המקדימות. במקום זאת, מעבירים רק את הנתונים והפונקציות שהם צריכים כפרמטרים.
אפשר להשתמש במופעים של ViewModel
כדי לנהל את המצב של קומפוזבלים ברמת מסך המשנה, אבל חשוב להכיר את מחזור החיים וההיקף של ViewModel
. אם הקומפוזיציה היא עצמאית, כדאי להשתמש ב-Hilt כדי להזריק את ViewModel
, וכך לא תצטרכו להעביר תלויות מקומפוזיציות אב.
אם למדד 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) } }
פעולות אסינכרוניות ב-Compose
Jetpack Compose מאפשרת לכם להפעיל פעולות אסינכרוניות באמצעות קורוטינות מתוך רכיבי ה-Composable.
מידע נוסף זמין במאמר תיעוד בנושא תופעות לוואי בנושאי ממשקי API LaunchedEffect
, produceState
ו-rememberCoroutineScope
.
ניווט
רכיב הניווט מספק תמיכה באפליקציות Jetpack פיתוח נייטיב. מידע נוסף זמין במאמרים ניווט באמצעות 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 משתלב גם עם ספריית הניווט של Compose. מוסיפים את יחסי התלות הנוספים הבאים לקובץ Gradle:
מגניב
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.2.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.2.0") }
כשמשתמשים ב-Navigation Compose, תמיד צריך להשתמש בפונקציה hiltViewModel
composable
כדי לקבל מופע של @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
שצריך להוסיף לפרויקט ולגרסה שלו.
דוגמה ל-Compose APIs של ספריית 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") } } }
מידע נוסף על השימוש בהחלפה בין דפים בכלי הכתיבה זמין במסמכי העזרה בנושא רשימות ורשתות.
מפות
אפשר להשתמש בספריית 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 מושבת
- תופעות לוואי ב-Compose
- State ו-Jetpack פיתוח נייטיב
- שמירת מצב ממשק המשתמש בכתיבה