ActivityResultLauncher: wat is het en hoe te gebruiken

Auteur: IT Sectr Gepubliceerd: 2026-06-10 Leestijd: 9 min

ActivityResultLauncher is een component van de Android Activity Result API, geïntroduceerd in versie Activity 1.2.0 van de androidx.activity-bibliotheek. Het vervangt de verouderde methoden startActivityForResult en onActivityResult, die sinds het begin deel uitmaakten van de Android SDK. Volgens Android Developers (2024) elimineert de nieuwe API de problemen van nauwe koppeling met Activity en het ontbreken van typeveiligheid. ActivityResultLauncher wordt vooraf geregistreerd en gebruikt Contract voor strikte typering van invoer- en uitvoergegevens.

Belangrijkste punten

  • ActivityResultLauncher — de nieuwe API voor het verkrijgen van een resultaat van Activity ter vervanging van de verouderde startActivityForResult
  • Contract — het object dat het type invoer- en uitvoergegevens voor een specifiek scenario definieert
  • Registratie gebeurt via registerForActivityResult vóór de aanroep van launch
  • Callback — wordt aangeroepen na voltooiing van de doel-Activity met het resultaat
  • API beschikbaar voor Activity, Fragment en Compose vanaf Activity 1.2.0

Wat is ActivityResultLauncher

ActivityResultLauncher is een klasse uit het pakket androidx.activity.result die een typeveilig mechanisme biedt voor het starten van Activity en het ontvangen van het resultaat. De Launcher wordt gemaakt via de methode registerForActivityResult, die twee parameters accepteert: Contract (beschrijft de invoer- en uitvoertypen) en ActivityResultCallback (de resultaatverwerker). Na registratie is de launcher klaar voor aanroep via de methode launch.

Het belangrijkste verschil met de oude API is de scheiding van registratie en lancering. Registratie vindt plaats in de initialisatiefase (Activity.onCreate of Fragment.onCreate), de callback wordt eenmalig aan de launcher gekoppeld en wordt gegarandeerd geactiveerd bij terugkeer van het resultaat. Dit elimineert het probleem dat onActivityResult in een onverwachte volgorde of op een vernietigde Activity werd geactiveerd.

ActivityResultLauncher ondersteunt alle scenario's die voorheen via onActivityResult werden afgehandeld: starten van camera, galerij, contacten aanvragen, machtigingen en aangepaste Activity's. Bovendien is de API uitbreidbaar: de ontwikkelaar kan eigen Contracten maken voor specifieke scenario's van gegevensuitwisseling tussen Activity's.

Waarom Activity Result API startActivityForResult verving

startActivityForResult maakte sinds API Level 1 (2008) deel uit van de Android SDK en bleef meer dan 12 jaar de belangrijkste manier om een resultaat van Activity te krijgen. Deze methode had echter fundamentele tekortkomingen die Google in de Activity Result API heeft verholpen. Laten we de belangrijkste problemen bekijken en hoe de nieuwe API ze oplost.

Probleem 1: nauwe koppeling met Activity

De methode startActivityForResult is gekoppeld aan Activity en Fragment via requestCode — een willekeurig geheel getal dat wordt doorgegeven aan onActivityResult. De ontwikkelaar moest handmatig de code koppelen aan de gestarte bewerking, wat leidde tot fouten bij hergebruik van code en overerving. ActivityResultLauncher elimineert requestCode volledig: de callback wordt in de registratiefase aan een specifieke launcher gekoppeld en wordt alleen daarvoor aangeroepen.

Probleem 2: verlies van resultaat bij schermrotatie

Bij configuratiewijzigingen (schermrotatie, taalwijziging) werd Activity opnieuw aangemaakt en kon onActivityResult niet worden geactiveerd — de callback ging verloren. Activity Result API slaat de status van de launcher automatisch op en herstelt deze via SavedStateRegistry, wat garandeert dat het resultaat wordt ontvangen, zelfs na het opnieuw aanmaken van Activity.

Probleem 3: gebrek aan typeveiligheid

De oude API gaf het resultaat door via Intent met Bundle, waarbij sleutels en gegevenstypen niet door de compiler werden gecontroleerd. Activity Result API gebruikt Contract — een generieke interface die het type invoergegevens (I) en het type resultaat (O) definieert. Typefouten worden gedetecteerd in de compilatiefase, niet tijdens runtime.

KenmerkstartActivityForResultActivityResultLauncher
RequestCodeHandmatig beheer vereistAutomatisch, niet nodig
TypeveiligheidNeeGeneric Contract
Behoud bij rotatieGaat verlorenSavedStateRegistry
Minimale APIAPI Level 1Activity 1.2.0
Gebruik in ComposeNiet ondersteundrememberLauncherForActivityResult

Belangrijkste contracten van Activity Result API

Contract is een interface ActivityResultContract<I, O> die definieert hoe Activity te starten en hoe het resultaat te interpreteren. Google biedt een set ingebouwde contracten voor typische scenario's die de meeste behoeften van de ontwikkelaar dekken.

StartIntentSenderForResult

StartIntentSenderForResult is het basiscontract voor het starten van IntentSender. Gebruikt in systeemscenario's, bijvoorbeeld bij authenticatie via Google Sign-In of bij betaling via Google Pay. Invoerparameter — PendingIntent, uitvoer — ActivityResult met code en Intent.

RequestMultiplePermissions

RequestMultiplePermissions is het contract voor het tegelijkertijd aanvragen van meerdere machtigingen in Android 6.0+. Invoerparameter — een String-array met machtigingsnamen, uitvoer — Map<String, Boolean> met het resultaat van elke aanvraag. Vroeger vereiste dit handmatige parsing in onRequestPermissionsResult met het matchen van aanvraagcodes.

TakePicture en TakeVideo

TakePicture is het contract voor het maken van foto's via de systeemcamera. Invoer — Uri waar de foto moet worden opgeslagen, uitvoer — Boolean (succes). TakeVideo werkt op dezelfde manier met video. Deze contracten vervangen de verouderde MediaStore.ACTION_IMAGE_CAPTURE met onstabiel gedrag op verschillende apparaten.

GetContent en OpenDocument

GetContent is het contract voor het selecteren van inhoud via de systeemkiezer. Invoer — MIME-type (bijv. image/*), uitvoer — Uri van het geselecteerde bestand. OpenDocument onderscheidt zich door ondersteuning voor meervoudige selectie en filtering op documenttypen. Beide contracten werken via SAF (Storage Access Framework).

CreateDocument en OpenDocumentTree

CreateDocument is het contract voor het maken van een nieuw document via het systeemdialoogvenster. De gebruiker kiest een naam en map, het systeem retourneert Uri om te schrijven. OpenDocumentTree geeft toegang tot een hele directory — de gebruiker kiest een map en de applicatie ontvangt een tree-uri voor het lezen en schrijven van alle bestanden erin.

Gebruik in Activity en Fragment

Het basispatroon voor het gebruik van ActivityResultLauncher in klassiek Android bestaat uit twee stappen: registratie via registerForActivityResult in de initialisatiefase en aanroep van launch als reactie op een gebruikersactie. Laten we een typisch voorbeeld van het selecteren van een afbeelding uit de galerij bekijken.

Registratie en lancering in Activity

Registreer de launcher in onCreate van de Activity — dit garandeert dat de callback gereed is vóór elke mogelijke aanroep. Registreer nooit de launcher vlak voor lancering — dit schendt het API-contract en kan leiden tot verlies van resultaat bij het opnieuw aanmaken van de 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/*")
    }
}

Gebruik in Fragment

In Fragment vindt registratie plaats in onCreate, onAttach of initialisatie in onCreateView. FragmentActivity geeft de launcher door via de bovenliggende Activity, zodat het resultaat binnen de Fragment wordt verwerkt, niet in de Activity. Dit verbetert de inkapseling in vergelijking met onActivityResult, waar alle resultaten van alle Fragmenten in één methode van de Activity werden verzameld.

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 biedt speciale composable-functionaliteit voor Activity Result API — rememberLauncherForActivityResult. In tegenstelling tot de klassieke benadering, wordt in Compose de launcher gemaakt als een object dat via remember aan de levenscyclus van de composable is gekoppeld. Dit maakt het mogelijk om de Activity Result API volledig declaratief te gebruiken zonder directe toegang tot Activity of Fragment.

rememberLauncherForActivityResult

rememberLauncherForActivityResult accepteert Contract en callback en retourneert ActivityResultLauncher. De launcher wordt bewaard bij recompositie en automatisch opgeruimd bij het verlaten van de compositie. De aanroep van launch vindt plaats als reactie op een gebeurtenis — bijvoorbeeld een knopdruk of statuswijziging.

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

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

Machtigingen afhandelen in Compose

Machtigingen aanvragen in Compose gebeurt ook via rememberLauncherForActivityResult met het contract RequestPermission of RequestMultiplePermissions. Google raadt het gebruik van accompanist-permissions aan, maar onder de motorkap gebruikt het ook Activity Result API. Voor het controleren van de machtigingsstatus is het handig om de status op te slaan in remember of ViewModel.

Veelvoorkomende fouten en beste praktijken

Activity Result API heeft veel problemen van de oude benadering geëlimineerd, maar onjuist gebruik kan leiden tot nieuwe soorten fouten. Laten we de meest voorkomende problemen bekijken en hoe u ze kunt vermijden.

Fout: registratie binnen een lambda of coroutine

Registratie van de launcher moet plaatsvinden bij initialisatie van het component — in onCreate van Activity of initialisator van Fragment. Als u de launcher registreert binnen een lambda, callback of coroutine, kan bij het opnieuw aanmaken van Activity de registratie opnieuw worden uitgevoerd en verliest de oude launcher de verbinding met het resultaat.

Fout: registratie van meerdere launchers met dezelfde sleutel

Elke launcher krijgt een unieke sleutel voor statusopslag. Als u twee launchers met hetzelfde Contract in één component registreert, kan SavedStateRegistry de status van de ene over de andere heen schrijven. Android Studio waarschuwt hiervoor via de lint-regel UnnecessaryRegisterForActivityResult, maar het is beter om de uniciteit handmatig te controleren.

Beste praktijk: behandel altijd null-resultaat

De gebruiker kan de actie annuleren — op de systeem-terugknop drukken, de app minimaliseren of overschakelen naar een andere app. In dit geval ontvangt de callback null of ActivityResult met RESULT_CANCELED. Controleer het resultaat altijd op null vóór gebruik om NullPointerException te voorkomen.

Beste praktijk: aangepaste Contracten voor herbruikbare logica

Als uw app vaak vergelijkbare scenario's start — bijvoorbeeld het selecteren van een contactpersoon met terugkeer van naam en telefoon — maak dan uw eigen Contract. Dit verbetert de leesbaarheid van de code en maakt het mogelijk om de logica van lancering en resultaatverwerking centraal te wijzigen.

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) }
}

Veelgestelde vragen

Kan ActivityResultLauncher in ViewModel worden gebruikt?

Nee — ActivityResultLauncher heeft Activity- of Fragment-context nodig voor registratie. Gebruik ViewModel alleen voor statusopslag en maak de launcher in Activity of Fragment en geef het resultaat door aan ViewModel.

Welke minimale SDK is vereist voor Activity Result API?

Activity Result API is beschikbaar vanaf bibliotheek activity-ktx 1.2.0. Minimale SDK — API Level 14 (Android 4.0), maar de meeste contracten werken alleen op API Level 19+.

Wat gebeurt er als launch twee keer wordt aangeroepen voordat het resultaat is ontvangen?

Herhaalde aanroep van launch vóór voltooiing van de eerste bewerking wordt genegeerd. Activity Result API ondersteunt geen parallelle lanceringen — wacht op de callback van de eerste bewerking vóór een nieuwe aanroep.

Waarmee vervang ik onActivityResult in oude code?

Migratie wordt uitgevoerd door de aanroep van startActivityForResult te vervangen door registerForActivityResult met het bijbehorende Contract. Verwijder onActivityResult en verwerk het resultaat in de callback van de launcher. Google biedt een migratiegids in de Android Developers-documentatie.

Werkt ActivityResultLauncher met bibliotheken zoals ML Kit of Barcode Scanner?

Ja, veel bibliotheken ondersteunen integratie via ActivityResultContracts. Bijvoorbeeld ML Kit Barcode Scanner gebruikt StartIntentSenderForResult om de scanner te starten. Raadpleeg de documentatie van de specifieke bibliotheek.

Samenvatting

  • ActivityResultLauncher — moderne typeveilige API ter vervanging van verouderde startActivityForResult
  • Contract definieert het type invoer- en uitvoergegevens, elimineert handmatig matchen van requestCode
  • Registratie vindt plaats in de initialisatiefase, resultaat wordt gegarandeerd geleverd via callback
  • Ingebouwde contracten dekken camera, galerij, machtigingen, documenten en contacten
  • Jetpack Compose gebruikt rememberLauncherForActivityResult voor het werken met de API
  • Aangepaste Contracten maken hergebruik van lanceerlogica tussen componenten mogelijk
  • API bewaart status bij configuratiewijzigingen via SavedStateRegistry

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook