ActivityResultLauncher: cos’è e come usarlo

Autore: IT Sectr Pubblicato: 2026-06-10 Tempo di lettura: 9 min

ActivityResultLauncher è un componente dell’API Activity Result di Android, introdotto nella versione Activity 1.2.0 della libreria androidx.activity. Sostituisce i metodi deprecati startActivityForResult e onActivityResult, che facevano parte dell’SDK Android fin dalla sua creazione. Secondo Android Developers (2024), la nuova API elimina i problemi di forte accoppiamento con Activity e la mancanza di type safety. ActivityResultLauncher viene registrato in anticipo e utilizza un Contract per la tipizzazione rigorosa dei dati di input e output.

Punti chiave

  • ActivityResultLauncher — una nuova API per ottenere risultati da un’Activity al posto del deprecato startActivityForResult
  • Contract — un oggetto che definisce il tipo di dati di input e output per uno scenario specifico
  • Registrazione effettuata tramite registerForActivityResult prima di chiamare launch
  • Callback invocato dopo che l’Activity di destinazione termina con un risultato
  • API disponibile per Activity, Fragment e Compose a partire da Activity 1.2.0

Cos’è ActivityResultLauncher

ActivityResultLauncher è una classe del pacchetto androidx.activity.result che fornisce un meccanismo type-safe per avviare un’Activity e ricevere un risultato. Il launcher viene creato tramite il metodo registerForActivityResult, che accetta due parametri: Contract (descrive i tipi di input e output) e ActivityResultCallback (gestore del risultato). Dopo la registrazione, il launcher è pronto per essere chiamato tramite il metodo launch.

La differenza chiave rispetto alla vecchia API è la separazione tra registrazione e avvio. La registrazione viene eseguita in fase di inizializzazione (Activity.onCreate o Fragment.onCreate), il callback viene associato al launcher una volta e viene garantito che si attivi quando il risultato torna. Questo elimina il problema per cui onActivityResult si attivava in un ordine imprevisto o su un’Activity distrutta.

ActivityResultLauncher supporta tutti gli scenari che venivano precedentemente gestiti tramite onActivityResult: avviare la fotocamera, la galleria, richiedere contatti, permessi e Activity personalizzate. Inoltre, l’API è estensibile: gli sviluppatori possono creare Contract personalizzati per scenari specifici di scambio di dati tra Activity.

Perché Activity Result API ha sostituito startActivityForResult

startActivityForResult ha fatto parte dell’SDK Android da API Level 1 (2008) ed è rimasto il metodo principale per ottenere un risultato da un’Activity per oltre 12 anni. Tuttavia, questo metodo aveva carenze fondamentali che Google ha risolto in Activity Result API. Esaminiamo i problemi principali e come la nuova API li risolve.

Problema 1: Forte accoppiamento con Activity

Il metodo startActivityForResult è legato ad Activity e Fragment tramite requestCode — un numero intero arbitrario passato a onActivityResult. Lo sviluppatore faceva corrispondere manualmente il codice all’operazione avviata, causando errori nel riutilizzo del codice e nell’ereditarietà. ActivityResultLauncher elimina completamente requestCode: il callback viene associato a un launcher specifico al momento della registrazione e viene invocato solo per quello.

Problema 2: Perdita del risultato durante la rotazione dello schermo

Durante i cambiamenti di configurazione (rotazione dello schermo, cambio lingua), l’Activity veniva ricreata e onActivityResult poteva non attivarsi — il callback veniva perso. Activity Result API salva e ripristina automaticamente lo stato del launcher tramite SavedStateRegistry, garantendo la ricezione del risultato anche dopo la ricreazione dell’Activity.

Problema 3: Mancanza di type safety

La vecchia API passava il risultato tramite Intent con un Bundle, dove chiavi e tipi di dati non venivano controllati dal compilatore. Activity Result API utilizza Contract — un’interfaccia generica che definisce il tipo di dati di input (I) e il tipo di risultato (O). Gli errori di incompatibilità dei tipi vengono rilevati in fase di compilazione, non in fase di esecuzione.

CaratteristicastartActivityForResultActivityResultLauncher
RequestCodeGestione manuale richiestaAutomatico, non richiesto
Type safetyNoContract generico
Salvataggio in rotazionePersoSavedStateRegistry
API minimaAPI Level 1Activity 1.2.0
Utilizzo in ComposeNon supportatorememberLauncherForActivityResult

Principali contratti di Activity Result API

Contract è l’interfaccia ActivityResultContract<I, O>, che definisce come avviare un’Activity e come interpretare il risultato. Google fornisce un set di contratti integrati per scenari tipici che coprono la maggior parte delle esigenze degli sviluppatori.

StartIntentSenderForResult

StartIntentSenderForResult — un contratto di base per avviare IntentSender. Utilizzato in scenari di sistema, ad esempio durante l’autorizzazione tramite Google Sign-In o i pagamenti tramite Google Pay. Il parametro di input è PendingIntent, l’output è ActivityResult con codice e Intent.

RequestMultiplePermissions

RequestMultiplePermissions — un contratto per richiedere più permessi contemporaneamente su Android 6.0+. Il parametro di input è un array di String con i nomi dei permessi, l’output è Map<String, Boolean> con il risultato di ogni richiesta. In precedenza ciò richiedeva l’analisi manuale in onRequestPermissionsResult con corrispondenza dei codici di richiesta.

TakePicture e TakeVideo

TakePicture — un contratto per scattare una foto tramite la fotocamera di sistema. L’input è un Uri dove salvare l’immagine, l’output è Boolean (successo). TakeVideo funziona in modo simile con i video. Questi contratti sostituiscono il deprecato MediaStore.ACTION_IMAGE_CAPTURE dal comportamento instabile su diversi dispositivi.

GetContent e OpenDocument

GetContent — un contratto per selezionare contenuti tramite il selettore di sistema. L’input è un tipo MIME (ad esempio image/*), l’output è un Uri del file selezionato. OpenDocument si differenzia supportando la selezione multipla e il filtraggio per tipo di documento. Entrambi i contratti funzionano tramite SAF (Storage Access Framework).

CreateDocument e OpenDocumentTree

CreateDocument — un contratto per creare un nuovo documento tramite il dialogo di sistema. L’utente sceglie un nome e una cartella, il sistema restituisce un Uri per la scrittura. OpenDocumentTree fornisce l’accesso a un’intera directory — l’utente seleziona una cartella e l’app riceve un tree-uri per leggere e scrivere tutti i file al suo interno.

Utilizzo in Activity e Fragment

Il modello di base per utilizzare ActivityResultLauncher in Android classico consiste in due passaggi: registrazione tramite registerForActivityResult in fase di inizializzazione e chiamata di launch in risposta a un’azione dell’utente. Esaminiamo un esempio tipico di selezione di un’immagine dalla galleria.

Registrazione e avvio in Activity

Registra il launcher nell’onCreate dell’Activity — questo garantisce che il callback sia pronto prima di qualsiasi possibile chiamata. Non registrare mai un launcher immediatamente prima di avviarlo — questo viola il contratto dell’API e può portare alla perdita del risultato durante la ricreazione dell’Activity.

kotlin
class MainActivity : AppCompatActivity() {
    private val pickImageLauncher =
        registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
            uri?.let { binding.imageView.setImageURI(it) }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        pickImageLauncher.launch("image/*")
    }
}

Utilizzo in Fragment

In un Fragment, la registrazione viene effettuata in onCreate, onAttach o nell’inizializzazione in onCreateView. FragmentActivity passa il launcher tramite l’Activity genitore, quindi il risultato viene elaborato all’interno del Fragment, non nell’Activity. Questo migliora l’incapsulamento rispetto a onActivityResult, dove tutti i risultati di tutti i Fragment venivano raccolti in un unico metodo dell’Activity.

kotlin
class ProfileFragment : Fragment() {
    private val cameraLauncher =
        registerForActivityResult(ActivityResultContracts.TakePicture()) { success ->
            if (success) { updateProfilePhoto() }
        }

    fun takePhoto(photoUri: Uri) {
        cameraLauncher.launch(photoUri)
    }
}

ActivityResultLauncher in Jetpack Compose

Jetpack Compose fornisce una funzione composable speciale per Activity Result API — rememberLauncherForActivityResult. A differenza dell’approccio classico, in Compose il launcher viene creato come un oggetto legato al ciclo di vita del composable tramite remember. Ciò consente di utilizzare Activity Result API completamente in stile dichiarativo senza accesso diretto ad Activity o Fragment.

rememberLauncherForActivityResult

rememberLauncherForActivityResult accetta un Contract e un callback, restituendo un ActivityResultLauncher. Il launcher viene preservato durante la ricomposizione e automaticamente cancellato quando si esce dalla composizione. La chiamata a launch avviene in risposta a un evento — ad esempio, un clic su un pulsante o un cambiamento di stato.

kotlin
@Composable
fun PhotoPicker() {
    val context = LocalContext.current
    val launcher = rememberLauncherForActivityResult(
        ActivityResultContracts.GetContent()
    ) { uri -> handleImage(uri) }

    Button(onClick = { launcher.launch("image/*") }) {
        Text("Scegli foto")
    }
}

Gestione dei permessi in Compose

Le richieste di permessi in Compose vengono effettuate anch’esse tramite rememberLauncherForActivityResult con il contratto RequestPermission o RequestMultiplePermissions. Google raccomanda di utilizzare accompanist-permissions, ma internamente utilizza anch’esso Activity Result API. Per tenere traccia dello stato dei permessi, è conveniente memorizzare lo stato in remember o ViewModel.

Errori comuni e best practices

Activity Result API ha eliminato molti problemi dell’approccio precedente, ma un utilizzo improprio può portare a nuovi tipi di errori. Esaminiamo i problemi più comuni e come evitarli.

Errore: registrazione all’interno di una lambda o coroutine

La registrazione del launcher deve essere effettuata durante l’inizializzazione del componente — nell’onCreate dell’Activity o nell’inizializzatore del Fragment. Se registri il launcher all’interno di una lambda, un callback o una coroutine, durante la ricreazione dell’Activity la registrazione potrebbe essere eseguita nuovamente e il vecchio launcher perderà la connessione con il risultato.

Errore: registrazione di più launcher con la stessa chiave

Ogni launcher riceve una chiave univoca per il salvataggio dello stato. Se registri due launcher con lo stesso Contract in un componente, SavedStateRegistry potrebbe sovrascrivere lo stato dell’uno con quello dell’altro. Android Studio avvisa di ciò tramite la regola lint UnnecessaryRegisterForActivityResult, ma è meglio controllare l’unicità manualmente.

Best Practice: gestire sempre il risultato nullo

L’utente può annullare l’azione — premere il pulsante indietro di sistema, ridurre a icona l’app o passare a un’altra app. In questo caso, il callback riceverà null o ActivityResult con RESULT_CANCELED. Controlla sempre se il risultato è null prima di utilizzarlo per evitare NullPointerException.

Best Practice: Contract personalizzati per logica riutilizzabile

Se la tua app avvia frequentemente scenari simili — ad esempio, selezionare un contatto e restituire nome e telefono — crea un Contract personalizzato. Ciò migliora la leggibilità del codice e consente modifiche centralizzate alla logica di avvio e gestione dei risultati.

kotlin
class PickContactContract : ActivityResultContract<Void, ContactData?>() {
    override fun createIntent(context: Context, input: Void?) =
        Intent(Intent.ACTION_PICK).setType(ContactsContract.Contacts.CONTENT_TYPE)

    override fun parseResult(resultCode: Int, intent: Intent?) =
        intent?.data?.let { queryContact(it) }
}

Domande frequenti

Si può usare ActivityResultLauncher in ViewModel?

No — ActivityResultLauncher richiede un contesto Activity o Fragment per la registrazione. Usa ViewModel solo per memorizzare lo stato e crea il launcher in Activity o Fragment e passa il risultato al ViewModel.

Quale SDK minimo è richiesto per Activity Result API?

Activity Result API è disponibile a partire dalla libreria activity-ktx 1.2.0. L’SDK minimo è API Level 14 (Android 4.0), ma la maggior parte dei contratti funziona solo su API Level 19+.

Cosa succede se launch viene chiamato due volte prima di ricevere un risultato?

Una chiamata ripetuta di launch prima del completamento della prima operazione verrà ignorata. Activity Result API non supporta avvii paralleli — attendi il callback della prima operazione prima di effettuare una nuova chiamata.

Come sostituire onActivityResult nel vecchio codice?

La migrazione viene effettuata sostituendo la chiamata startActivityForResult con registerForActivityResult utilizzando il Contract appropriato. Rimuovi onActivityResult e gestisci il risultato nel callback del launcher. Google fornisce una guida alla migrazione nella documentazione di Android Developers.

ActivityResultLauncher funziona con librerie come ML Kit o Barcode Scanner?

, molte librerie supportano l’integrazione tramite ActivityResultContracts. Ad esempio, ML Kit Barcode Scanner utilizza StartIntentSenderForResult per avviare lo scanner. Controlla la documentazione della libreria specifica.

Riepilogo

  • ActivityResultLauncher — un’API moderna type-safe che sostituisce il deprecato startActivityForResult
  • Contract definisce i tipi di dati di input e output, eliminando la corrispondenza manuale di requestCode
  • Registrazione effettuata all’inizializzazione, il risultato viene consegnato garantitamente tramite callback
  • Contratti integrati coprono fotocamera, galleria, permessi, documenti e contatti
  • Jetpack Compose utilizza rememberLauncherForActivityResult per lavorare con l’API
  • Contract personalizzati consentono di riutilizzare la logica di avvio tra componenti
  • API preserva lo stato durante i cambiamenti di configurazione tramite SavedStateRegistry

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche