Vous pouvez utiliser vos bibliothèques préférées dans Compose. Cette section vous présente comment intégrer quelques-unes des bibliothèques les plus utiles.
Activité
Pour utiliser Compose dans une activité, vous devez utiliser ComponentActivity
, une sous-classe de Activity
qui fournit les LifecycleOwner
et les composants appropriés à Compose. Elle fournit également des API supplémentaires qui dissocient votre code pour ne pas remplacer les méthodes dans votre classe d'activité.
Activity Compose expose ces API à des composables. Il n'est donc plus nécessaire de remplacer les méthodes en dehors de vos composables ou de récupérer une instance Activity
explicite.
De plus, ces API garantissent que les composables qu'elles ne sont initialisées qu'une seule fois, qu'elles survivent à la recomposition et qu'elles sont supprimées proprement si le composable est supprimé de la composition.
Résultat d'activité
L'API rememberLauncherForActivityResult()
vous permet d'obtenir un résultat depuis une activité dans votre 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" ) } }
Cet exemple illustre un contrat GetContent()
simple. Appuyez sur le bouton pour lancer la demande. Le lambda de fin pour rememberLauncherForActivityResult()
est appelé une fois que l'utilisateur sélectionne une image et revient au lancement de l'activité.
L'image sélectionnée est chargée à l'aide de la fonction rememberImagePainter()
de Coil.
N'importe quelle sous-classe de ActivityResultContract
peut être utilisée comme premier argument de rememberLauncherForActivityResult()
.
Cela signifie que vous pouvez utiliser cette technique pour demander du contenu au framework et d'autres modèles courants. Vous pouvez également créer vos propres contrats personnalisés et les utiliser avec cette technique.
Demander des autorisations d'exécution
Il est possible d'utiliser l'API Activity Result et rememberLauncherForActivityResult()
, mentionnés ci-dessus, pour demander des autorisations d'exécution à l'aide du contrat RequestPermission
pour une seule autorisation ou du contrat RequestMultiplePermissions
pour plusieurs autorisations.
La bibliothèque d'autorisations Accompanist peut également être utilisée au-dessus de ces API pour mapper l'état actuel des autorisations accordées à l'état que votre UI Compose peut utiliser.
Gérer le bouton "Retour" du système
Pour fournir une navigation Retour personnalisée et remplacer le comportement par défaut du bouton Retour du système depuis votre composable, votre composable peut utiliser un BackHandler
pour intercepter cet événement :
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
Le premier argument contrôle si BackHandler
est actuellement activé. Cet argument vous permet de désactiver temporairement votre gestionnaire en fonction de l'état de votre composant. Le lambda de fin sera appelé si l'utilisateur déclenche un événement système et si BackHandler
est actuellement activé.
ViewModel
Si vous utilisez la bibliothèque Composants de l'architecture ViewModel, vous pouvez accéder à un ViewModel
à partir de n'importe quel composable en appelant la méthode viewModel()
. Ajoutez la dépendance suivante à votre fichier Gradle:
Groovy
dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5' }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5") }
Vous pouvez ensuite utiliser la fonction viewModel()
dans votre code.
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { // use viewModel here }
viewModel()
renvoie un ViewModel
existant ou en crée un. Par défaut, le ViewModel
renvoyé est limité à l'activité, au fragment ou à la destination de navigation englobants, et est conservé tant que le champ d'application est actif.
Par exemple, si le composable est utilisé dans une activité, viewModel()
renvoie la même instance jusqu'à la fin de l'activité ou la fermeture du processus.
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 ) { /* ... */ }
Consignes d'utilisation
Vous accédez généralement aux instances ViewModel
au niveau des composables au niveau de l'écran, c'est-à-dire à proximité d'un composable racine appelé à partir d'une activité, d'un fragment ou d'une destination d'un graphique de navigation. En effet, les ViewModel
sont par défaut limitées à ces objets au niveau de l'écran. Pour en savoir plus sur le cycle de vie et la portée d'un ViewModel
, consultez cet article.
Essayez d'éviter de transmettre des instances ViewModel
à d'autres composables, car cela peut rendre ces composables plus difficiles à tester et peut endommager les aperçus. Au lieu de cela, transmettez les données et les fonctions dont ils ont besoin en tant que paramètres.
Vous pouvez utiliser des instances ViewModel
pour gérer l'état des composables au niveau de l'écran secondaire. Toutefois, tenez compte du cycle de vie et de la portée de ViewModel
. Si le composable est autonome, vous pouvez envisager d'utiliser Hilt pour injecter le ViewModel
afin d'éviter de transmettre des dépendances de composables parents.
Si votre ViewModel
comporte des dépendances, viewModel()
accepte un paramètre ViewModelProvider.Factory
facultatif.
Pour en savoir plus sur le ViewModel
dans Compose et sur l'utilisation des instances avec la bibliothèque Navigation de Compose, ou sur les activités et les fragments, consultez la documentation sur l'interopérabilité.
Flux de données
Compose propose des extensions pour les plus grandes solutions Android basées sur les flux. Chacune de ces extensions est fournie par un artefact différent :
LiveData.observeAsState()
inclus dans l'artefactandroidx.compose.runtime:runtime-livedata:$composeVersion
.Flow.collectAsState()
ne nécessite pas de dépendances supplémentaires.Observable.subscribeAsState()
inclus dans l'artefactandroidx.compose.runtime:runtime-rxjava2:$composeVersion
ouandroidx.compose.runtime:runtime-rxjava3:$composeVersion
.
Ces artefacts s'enregistrent en tant qu'écouteur et représentent les valeurs sous la forme d'un State
. Chaque fois qu'une nouvelle valeur est émise, Compose recompose les parties de l'UI où state.value
est utilisée. Par exemple, dans ce code, ShowData
se recompose chaque fois que exampleLiveData
émet une nouvelle valeur.
// 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) } }
Opérations asynchrones dans Compose
Jetpack Compose vous permet d'exécuter des opérations asynchrones à l'aide de coroutines depuis vos composables.
Consultez les API LaunchedEffect
, produceState
et rememberCoroutineScope
dans la documentation sur les effets secondaires pour en savoir plus.
Navigation
Le composant Navigation est compatible avec les applications Jetpack Compose. Pour en savoir plus, consultez Naviguer avec Compose et Migrer la navigation Jetpack vers Navigation Compose.
Hilt
Il s'agit de la solution recommandée pour l'injection de dépendances dans les applications Android. Elle fonctionne parfaitement avec Compose.
La fonction viewModel()
mentionnée dans la section ViewModel utilise automatiquement le ViewModel que Looker construit avec l'annotation @HiltViewModel
. Nous avons fourni de la documentation sur l'intégration de ViewModel pour 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 et Navigation
Hilt s'intègre également à la bibliothèque de navigation Compose. Ajoutez les dépendances supplémentaires suivantes à votre fichier Gradle :
Groovy
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.2.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.2.0") }
Lorsque vous utilisez Navigation Compose, utilisez toujours la fonction modulable hiltViewModel
pour obtenir une instance de votre ViewModel
annotée @HiltViewModel
.
Cela fonctionne avec les fragments ou les activités annotés avec @AndroidEntryPoint
.
Par exemple, si ExampleScreen
est une destination dans un graphique de navigation, appelez hiltViewModel()
pour obtenir une instance de ExampleViewModel
limitée à la destination, comme indiqué dans l'extrait de code ci-dessous :
// 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) } /* ... */ } }
Si vous devez récupérer l'instance d'un ViewModel
limité aux itinéraires de navigation ou au graphique de navigation, utilisez hiltViewModel
et transmettez la valeur backStackEntry
correspondante en tant que paramètre :
// 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) } } } }
Paging
La bibliothèque Paging facilite le chargement progressif des données. Elle est compatible avec Compose.
La page des versions de Paging contient des informations sur la dépendance paging-compose
supplémentaire à ajouter au projet et à sa version.
Voici un exemple des API Compose de la bibliothèque 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") } } }
Pour en savoir plus sur l'utilisation de Paging dans Compose, consultez la documentation sur les listes et les grilles.
Maps
La bibliothèque Maps Compose vous permet de proposer Google Maps dans votre application. Voici un exemple d'utilisation :
@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" ) } }
Recommandations personnalisées
- Remarque : Le texte du lien s'affiche lorsque JavaScript est désactivé
- Effets secondaires dans Compose
- États et Jetpack Compose
- Enregistrer l'état de l'UI dans Compose