Puoi utilizzare le tue librerie preferite in Compose. Questa sezione descrive come incorporare alcune delle librerie più utili.
Attività
Per utilizzare Compose in un'attività, devi utilizzare
ComponentActivity,
una sottoclasse di Activity che fornisce i componenti e
LifecycleOwner appropriati a Compose. Fornisce anche API aggiuntive che dissociano il codice dalla sostituzione dei metodi nella classe di attività.
Activity Compose
espone queste API ai componibili in modo che non sia più necessario sostituire i metodi al di fuori dei
componibili o recuperare un'istanza Activity esplicita.
Inoltre, queste API garantiscono che vengano inizializzate una sola volta, che sopravvivano alla ricomposizione e che vengano pulite correttamente se il componibile viene rimosso dalla composizione.
Risultato dell'attività
L'
rememberLauncherForActivityResult()
API ti consente di
ottenere un risultato da un'attività
nel tuo componibile:
@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" ) } }
Questo esempio mostra un semplice
GetContent()
contratto. Toccando il pulsante viene avviata la richiesta. La lambda finale per
rememberLauncherForActivityResult()
viene richiamata quando l'utente seleziona un'immagine e torna all'attività di avvio.
In questo modo viene caricata l'immagine selezionata utilizzando la funzione rememberImagePainter() di Coil.
Qualsiasi sottoclasse di
ActivityResultContract
può essere utilizzata come primo argomento di
rememberLauncherForActivityResult().
Ciò significa che puoi utilizzare questa tecnica per richiedere contenuti dal framework e in altri pattern comuni. Puoi anche creare i tuoi
contratti personalizzati e utilizzarli con
questa tecnica.
Richiesta delle autorizzazioni di runtime
La stessa API Risultato dell'attività e
rememberLauncherForActivityResult()
spiegate sopra possono essere utilizzate per
richiedere le autorizzazioni di runtime
utilizzando il
RequestPermission
contratto per una singola autorizzazione o il
RequestMultiplePermissions
contratto per più autorizzazioni.
La libreria Accompanist Permissions può essere utilizzata anche come livello sopra queste API per mappare lo stato concesso corrente per le autorizzazioni nello stato che l'UI Compose può utilizzare.
Gestione del pulsante Indietro del sistema
Per fornire una navigazione a ritroso personalizzata
e sostituire il comportamento predefinito del pulsante Indietro del sistema all'interno del
componibile, il componibile può utilizzare un
BackHandler
per intercettare l'evento:
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
Il primo argomento controlla se il
BackHandler
è attualmente abilitato. Puoi utilizzare questo argomento per disattivare temporaneamente il gestore
in base allo stato del componente. La lambda finale verrà richiamata se l'
utente attiva un evento Indietro del sistema e
BackHandler
è attualmente abilitato.
ViewModel
Se utilizzi la libreria ViewModel
dei componenti dell'architettura, puoi accedere a un
ViewModel da qualsiasi componibile
chiamando la funzione
viewModel(). Aggiungi la seguente dipendenza al file Gradle:
Alla moda
dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0' }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0") }
Puoi quindi utilizzare la funzione viewModel() nel codice.
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { // use viewModel here }
viewModel() restituisce un ViewModel esistente o ne crea uno nuovo. Per impostazione predefinita, ViewModel restituito è limitato all'attività, al fragment o alla destinazione di navigazione racchiusi e viene conservato finché l'ambito è attivo.
Ad esempio, se il componibile viene utilizzato in un'attività, viewModel() restituisce la stessa istanza finché l'attività non viene completata o il processo non viene terminato.
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 ) { /* ... */ }
Linee guida sull'utilizzo
In genere si accede alle istanze ViewModel nei componibili a livello di schermata, ovvero vicino a un componibile principale chiamato da un'attività, un fragment o una destinazione di un grafico di navigazione. Questo perché, per impostazione predefinita, ViewModel sono limitati a questi oggetti a livello di schermata. Scopri di più sul ciclo di vita e sull'ambito di un
ViewModel's
qui.
Cerca di evitare di passare le istanze
ViewModel ad altri componibili, in quanto ciò può rendere questi componibili
più difficili da testare e può interrompere le
anteprime. Passa invece solo i dati e le funzioni di cui hanno bisogno come parametri.
Puoi utilizzare le ist2/}anze per
gestire lo stato dei componibili a livello di schermata secondaria, ma tieni presente il
ViewModel's
ciclo di vita e l'ambito.ViewModel Se il
componibile è autonomo, potresti prendere in considerazione l'utilizzo di Hilt per
inserire il ViewModel per evitare di dover passare le dipendenze dai componibili principali.
Se il tuo ViewModel ha dipendenze, viewModel() accetta un
ViewModelProvider.Factory
facoltativo come parametro.
Per ulteriori informazioni su ViewModel in Compose e su come vengono utilizzate le istanze
con la libreria Navigation Compose o con attività e fragment,
consulta la documentazione sull'interoperabilità.
Stream di dati
Compose include estensioni per le soluzioni basate su stream più diffuse di Android. Ciascuna di queste estensioni è fornita da un artefatto diverso:
LiveData.observeAsState()incluso nell'artefattoandroidx.compose.runtime:runtime-livedata:$composeVersion.Flow.collectAsState()non richiede dipendenze aggiuntive.Observable.subscribeAsState()incluso nell'artefattoandroidx.compose.runtime:runtime-rxjava2:$composeVersionoandroidx.compose.runtime:runtime-rxjava3:$composeVersion.
Questi artefatti vengono registrati come listener e rappresentano i valori come a
State. Ogni volta che viene emesso un nuovo valore, Compose ricompone le parti dell'UI in cui viene utilizzato state.value. Ad esempio, in questo codice, ShowData viene ricomposto ogni volta che
exampleLiveData emette un nuovo valore.
// 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) } }
Operazioni asincrone in Compose
Jetpack Compose ti consente di eseguire operazioni asincrone utilizzando le coroutine all'interno dei componibili.
Per ulteriori informazioni, consulta le API LaunchedEffect, produceState e rememberCoroutineScope nella documentazione sugli effetti collaterali.
Navigazione
Il componente di navigazione fornisce il supporto per le applicazioni Jetpack Compose. Per ulteriori informazioni, consulta Navigare con Compose e Migrare la navigazione Jetpack a Navigation Compose.
Hilt
Hilt è la soluzione consigliata per l'inserimento delle dipendenze nelle app Android e funziona perfettamente con Compose.
La funzione viewModel() menzionata nella sezione ViewModel
utilizza automaticamente il ViewModel che Hilt crea con l'annotazione @HiltViewModel. Abbiamo fornito la documentazione con informazioni sull'integrazione di ViewModel di 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 e navigazione
Hilt si integra anche con la libreria Navigation Compose. Aggiungi le seguenti dipendenze aggiuntive al file Gradle:
Alla moda
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.3.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.3.0") }
Quando utilizzi Navigation Compose, usa sempre la funzione componibile hiltViewModel per ottenere un'istanza di @HiltViewModel annotata con ViewModel.
Funziona con i fragment o le attività annotati con @AndroidEntryPoint.
Ad esempio, se ExampleScreen è una destinazione in un grafico di navigazione, chiama hiltViewModel() per ottenere un'istanza di ExampleViewModel limitata alla destinazione, come mostrato nello snippet di codice seguente:
// 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) } /* ... */ } }
Se devi recuperare l'istanza di un ViewModel limitata alle
route di navigazione o al
grafico di navigazione
invece, utilizza la funzione componibile hiltViewModel e passa il
backStackEntry corrispondente come parametro:
// 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 libreria Paging
semplifica il caricamento graduale dei dati ed è supportata in Compose.
La pagina di release di Paging
contiene
informazioni sulla dipendenza paging-compose aggiuntiva che deve essere aggiunta
al progetto e alla relativa versione.
Ecco un esempio delle API Compose della libreria 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") } } }
Per ulteriori informazioni sull'utilizzo di Paging in Compose, consulta la documentazione Elenchi e griglie.
Maps
Puoi utilizzare la libreria Maps Compose per fornire Google Maps nella tua app. Ecco un esempio di utilizzo:
@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" ) } }
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Effetti collaterali in Compose
- Stato e Jetpack Compose
- Salvare lo stato dell'UI in Compose