אתם יכולים להשתמש בספריות המועדפות עליכם בחלונית הכתיבה. בקטע הזה נסביר איך לשלב כמה מהספריות השימושיות ביותר.
פעילות
כדי להשתמש ב-Compose בפעילות, צריך להשתמש ב-ComponentActivity
, Subclass של Activity
שמספק את ה-LifecycleOwner
והרכיבים המתאימים ל-Compose. בנוסף, הוא מספק ממשקי API נוספים שמאפשרים לבטל את הקישור בין הקוד לבין שיטות שינוי ברירת המחדל (overriding) בכיתה של הפעילות.
Activity Compose חושף את ממשקי ה-API האלה לרכיבים הניתנים ליצירה, כך שכבר לא צריך לשנות את שיטות ה-override מחוץ לרכיבים הניתנים ליצירה או לאחזר מכונה מפורשת של Activity
.
בנוסף, ממשקי ה-API האלה מבטיחים שהם יופעלו רק פעם אחת, יעברו עיבוד מחדש וייסגרו כראוי אם הרכיב הניתן ליצירה יוסר מההרכב.
תוצאת הפעילות
ה-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()
.
המשמעות היא שאפשר להשתמש בשיטה הזו כדי לבקש תוכן מהמסגרת ובתבניות נפוצות אחרות. אפשר גם ליצור חוזים מותאמים אישית ולהשתמש בהם בשיטה הזו.
שליחת בקשה להרשאות בזמן ריצה
אפשר להשתמש באותו Activity Result API וב-rememberLauncherForActivityResult()
שמתוארים למעלה כדי לבקש הרשאות בסביבת זמן הריצה באמצעות החוזה RequestPermission
להרשאה אחת או החוזה RequestMultiplePermissions
לכמה הרשאות.
אפשר גם להשתמש בספריית ההרשאות של Compose בשכבה מעל ממשקי ה-API האלה כדי למפות את המצב הנוכחי של ההרשאות שהוקצו למצב שאפשר להשתמש בו בממשק המשתמש של Compose.
טיפול בלחצן 'הקודם' במערכת
כדי לספק ניווט מותאם אישית אחורה ולעקוף את התנהגות ברירת המחדל של לחצן החזרה אחורה במערכת מתוך ה-Composable, אפשר להשתמש ב-Composable ב-BackHandler
כדי ליירט את האירוע הזה:
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
הארגומנט הראשון קובע אם האירוע BackHandler
מופעל כרגע. אפשר להשתמש בארגומנט הזה כדי להשבית את הטיפול באופן זמני על סמך מצב הרכיב. הפונקציה lambda שבסוף תופעל אם המשתמש יפעיל אירוע חזרה למערכת, ו-BackHandler
מופעל כרגע.
ViewModel
אם משתמשים בספרייה Architecture Components ViewModel, אפשר לגשת ל-ViewModel
מכל רכיב מורכב על ידי קריאה לפונקציה viewModel()
. מוסיפים את יחסי התלות הבאים לקובץ Gradle:
Groovy
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
מוגבל לפעילות, לקטע או ליעד הניווט המקיפים, ונשמר כל עוד ההיקף פעיל.
לדוגמה, אם משתמשים ב-composable בפעילות, 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
ברכיבי Composable ברמת המסך, כלומר ליד רכיב Composable ברמה הבסיסית (root) שנקרא מפעילות, מקטע או יעד בתרשים ניווט. הסיבה לכך היא שכברירת מחדל, משתני ViewModel
מוגדרים ברמת האובייקטים האלה ברמת המסך. מידע נוסף על מחזור החיים וההיקף של ViewModel
זמין כאן.
נסו להימנע ממעבר של מכונות ViewModel
לרכיבים אחרים של Composable, כי זה עלול להקשות על בדיקת הרכיבים האלה ולגרום לשיבושים בתצוגות המקדימות. במקום זאת, מעבירים רק את הנתונים והפונקציות שנדרשים להם כפרמטרים.
אפשר להשתמש במופעי ViewModel
כדי לנהל את המצב של רכיבים מורכבים ברמת המסך המשני, אבל חשוב לזכור את מחזור החיים וההיקף של ViewModel
. אם הרכיב הניתן לקיבוץ הוא עצמאי, מומלץ להשתמש ב-Hilt כדי להחדיר את ViewModel
, כדי שלא תצטרכו להעביר יחסי תלות מרכיבים ניתנים לקיבוץ ברמה ההורה.
אם ל-ViewModel
יש יחסי תלות, viewModel()
מקבל פרמטר אופציונלי של ViewModelProvider.Factory
.
מידע נוסף על ViewModel
ב-Compose ועל האופן שבו נעשה שימוש במופעים עם ספריית Navigation Compose, או עם פעילויות וקטעי קוד, זמין במסמכי העזרה בנושא יכולת פעולה הדדית.
מקורות נתונים
Compose מגיע עם תוספים לפתרונות הפופולריים ביותר של Android שמבוססים על סטרימינג. כל אחד מהתוספים האלה מסופק על ידי ארטיפקט אחר:
LiveData.observeAsState()
נכלל ב-Artifact שלandroidx.compose.runtime:runtime-livedata:$composeVersion
.Flow.collectAsState()
לא מחייב יחסי תלות נוספים.Observable.subscribeAsState()
נכלל ב-artifactandroidx.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 אפשר להריץ פעולות אסינכרוניות באמצעות קורוטינים מתוך הרכיבים הניתנים להחלפה.
מידע נוסף זמין בממשקי ה-API LaunchedEffect
, produceState
ו-rememberCoroutineScope
במאמר תיעוד לגבי תופעות לוואי.
ניווט
רכיב הניווט מספק תמיכה באפליקציות של Jetpack פיתוח נייטיב. מידע נוסף זמין במאמרים ניווט באמצעות Compose והעברה של ניווט ב-Jetpack ל-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:
Groovy
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.2.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.2.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-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") } } }
מידע נוסף על השימוש בחלוקה לדפים ב-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 מושבת
- תופעות לוואי ב-Compose
- State ו-Jetpack פיתוח נייטיב
- שמירת מצב ממשק המשתמש ב'כתיבה'