ActivityResultLauncher: vad är det och hur man använder

Författare: IT Sectr Publicerad: 2026-06-10 Lästid: 9 min

ActivityResultLauncher är en komponent i Android Activity Result API, introducerad i version Activity 1.2.0 av androidx.activity-biblioteket. Den ersätter de föråldrade metoderna startActivityForResult och onActivityResult, som har varit en del av Android SDK sedan dess skapelse. Enligt Android Developers (2024) eliminerar det nya API:et problemen med tät koppling till Activity och bristen på typsäkerhet. ActivityResultLauncher registreras i förväg och använder Contract för strikt typning av in- och utdata.

Huvudpunkter

  • ActivityResultLauncher — det nya API:et för att få resultat från Activity istället för den föråldrade startActivityForResult
  • Contract — objektet som definierar typen av in- och utdata för ett specifikt scenario
  • Registrering görs via registerForActivityResult före anropet launch
  • Callback — anropas efter att mål-Activity har slutförts med resultatet
  • API tillgängligt för Activity, Fragment och Compose från och med Activity 1.2.0

Vad är ActivityResultLauncher

ActivityResultLauncher är en klass från paketet androidx.activity.result som tillhandahåller en typsäker mekanism för att starta Activity och ta emot resultatet. Launcher skapas via metoden registerForActivityResult, som tar två parametrar: Contract (beskriver in- och utdatatyper) och ActivityResultCallback (resultathanteraren). Efter registrering är launcher redo för anrop via metoden launch.

Den viktigaste skillnaden jämfört med det gamla API:et är separationen av registrering och start. Registrering sker i initieringsfasen (Activity.onCreate eller Fragment.onCreate), callback kopplas till launcher en gång och garanteras aktiveras när resultatet returneras. Detta eliminerar problemet när onActivityResult aktiverades i oväntad ordning eller på en förstörd Activity.

ActivityResultLauncher stöder alla scenarier som tidigare hanterades via onActivityResult: starta kamera, galleri, begära kontakter, behörigheter och anpassade Activity. Dessutom är API:et utbyggbart: utvecklaren kan skapa egna Contract för specifika scenarier för datautbyte mellan Activity.

Varför Activity Result API ersatte startActivityForResult

startActivityForResult har varit en del av Android SDK sedan version API Level 1 (2008) och förblev det främsta sättet att få resultat från Activity i över 12 år. Men denna metod hade grundläggande brister som Google åtgärdade i Activity Result API. Låt oss titta på de viktigaste problemen och hur det nya API:et löser dem.

Problem 1: tät koppling till Activity

Metoden startActivityForResult är kopplad till Activity och Fragment via requestCode — ett godtyckligt heltal som skickas till onActivityResult. Utvecklaren matchade manuellt koden med den startade operationen, vilket ledde till fel vid återanvändning av kod och arv. ActivityResultLauncher eliminerar requestCode helt: callback kopplas till en specifik launcher i registreringsfasen och anropas endast för den.

Problem 2: förlust av resultat vid skärmrotation

Vid konfigurationsändringar (skärmrotation, språkbyte) återskapades Activity och onActivityResult kunde inte aktiveras — callback gick förlorad. Activity Result API sparar och återställer automatiskt launchens tillstånd via SavedStateRegistry, vilket garanterar att resultatet tas emot även efter återskapande av Activity.

Problem 3: brist på typsäkerhet

Det gamla API:et överförde resultatet via Intent med Bundle, där nycklar och datatyper inte kontrollerades av kompilatorn. Activity Result API använder Contract — ett generiskt gränssnitt som definierar typen av indata (I) och typen av resultat (O). Typfel upptäcks i kompileringsfasen, inte vid körning.

EgenskapstartActivityForResultActivityResultLauncher
RequestCodeKräver manuell hanteringAutomatisk, krävs inte
TypsäkerhetNejGeneric Contract
Bevarande vid rotationFörlorasSavedStateRegistry
Minsta APIAPI Level 1Activity 1.2.0
Användning i ComposeStöds interememberLauncherForActivityResult

Huvudkontrakt i Activity Result API

Contract är ett gränssnitt ActivityResultContract<I, O> som definierar hur Activity ska startas och hur resultatet ska tolkas. Google tillhandahåller en uppsättning inbyggda kontrakt för typiska scenarier som täcker de flesta utvecklarbehov.

StartIntentSenderForResult

StartIntentSenderForResult är grundkontraktet för att starta IntentSender. Används i systemscenarier, till exempel vid autentisering via Google Sign-In eller betalning via Google Pay. Indataparameter — PendingIntent, utdata — ActivityResult med kod och Intent.

RequestMultiplePermissions

RequestMultiplePermissions är kontraktet för att begära flera behörigheter samtidigt i Android 6.0+. Indataparameter — en String-array med behörighetsnamn, utdata — Map<String, Boolean> med resultatet av varje begäran. Tidigare krävde detta manuell tolkning i onRequestPermissionsResult med matchning av begärandekoder.

TakePicture och TakeVideo

TakePicture är kontraktet för att ta foto via systemkameran. Indata — Uri där fotot sparas, utdata — Boolean (framgång). TakeVideo fungerar på liknande sätt med video. Dessa kontrakt ersätter den föråldrade MediaStore.ACTION_IMAGE_CAPTURE med instabilt beteende på olika enheter.

GetContent och OpenDocument

GetContent är kontraktet för att välja innehåll via systemväljaren. Indata — MIME-typ (t.ex. image/*), utdata — Uri för den valda filen. OpenDocument skiljer sig genom stöd för flerval och filtrering efter dokumenttyper. Båda kontrakten fungerar via SAF (Storage Access Framework).

CreateDocument och OpenDocumentTree

CreateDocument är kontraktet för att skapa ett nytt dokument via systemdialogrutan. Användaren väljer namn och mapp, systemet returnerar Uri för skrivning. OpenDocumentTree ger åtkomst till en hel katalog — användaren väljer en mapp och applikationen får tree-uri för att läsa och skriva alla filer inuti.

Användning i Activity och Fragment

Grundmönstret för att använda ActivityResultLauncher i klassisk Android består av två steg: registrering via registerForActivityResult i initieringsfasen och anrop av launch som svar på en användaråtgärd. Låt oss titta på ett typiskt exempel på att välja en bild från galleriet.

Registrering och start i Activity

Registrera launchern i Activitys onCreate — detta garanterar att callback är redo före varje möjligt anrop. Registrera aldrig launchern omedelbart före start — detta bryter mot API-kontraktet och kan leda till förlust av resultat vid återskapande av 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/*")
    }
}

Användning i Fragment

I Fragment sker registrering i onCreate, onAttach eller initiering i onCreateView. FragmentActivity skickar launchern via den överordnade Activity, så resultatet bearbetas inuti Fragment, inte i Activity. Detta förbättrar inkapslingen jämfört med onActivityResult, där alla resultat från alla Fragment samlades i en enda metod i Activity.

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

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

ActivityResultLauncher i Jetpack Compose

Jetpack Compose tillhandahåller speciell composable-funktionalitet för Activity Result API — rememberLauncherForActivityResult. Till skillnad från den klassiska metoden skapas launchern i Compose som ett objekt kopplat till composablens livscykel via remember. Detta gör det möjligt att använda Activity Result API helt deklarativt utan direkt åtkomst till Activity eller Fragment.

rememberLauncherForActivityResult

rememberLauncherForActivityResult tar emot Contract och callback och returnerar ActivityResultLauncher. Launchern bevaras vid rekomposition och rensas automatiskt vid utträde ur kompositionen. Anropet launch sker som svar på en händelse — till exempel knapptryckning eller statusändring.

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

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

Hantering av behörigheter i Compose

Begäran om behörigheter i Compose görs också via rememberLauncherForActivityResult med kontraktet RequestPermission eller RequestMultiplePermissions. Google rekommenderar att använda accompanist-permissions, men under huven använder det också Activity Result API. För att kontrollera behörighetsstatus är det bekvämt att lagra status i remember eller ViewModel.

Vanliga misstag och bästa praxis

Activity Result API har eliminerat många problem med den gamla metoden, men felaktig användning kan leda till nya typer av fel. Låt oss titta på de vanligaste problemen och hur man undviker dem.

Misstag: registrering inuti lambda eller korutin

Registrering av launchern måste ske vid initiering av komponenten — i Activitys onCreate eller Fragments initierare. Om du registrerar launchern inuti en lambda, callback eller korutin, kan registreringen utföras igen när Activity återskapas och den gamla launchern förlorar kopplingen till resultatet.

Misstag: registrering av flera launchers med samma nyckel

Varje launcher får en unik nyckel för att spara tillstånd. Om du registrerar två launchers med samma Contract i en komponent kan SavedStateRegistry skriva över den enas tillstånd med den andras. Android Studio varnar om detta via lint-regeln UnnecessaryRegisterForActivityResult, men det är bättre att kontrollera unikheten manuellt.

Bästa praxis: hantera alltid null-resultat

Användaren kan avbryta åtgärden — trycka på systemets bakåtknapp, minimera appen eller byta till en annan app. I detta fall kommer callback att få null eller ActivityResult med RESULT_CANCELED. Kontrollera alltid resultatet för null före användning för att undvika NullPointerException.

Bästa praxis: anpassade Contract för återanvändbar logik

Om din app ofta startar liknande scenarier — till exempel att välja en kontakt med returnering av namn och telefon — skapa ditt eget Contract. Detta förbättrar kodens läsbarhet och möjliggör centraliserad ändring av logiken för start och resultathantering.

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

Vanliga frågor

Kan ActivityResultLauncher användas i ViewModel?

Nej — ActivityResultLauncher kräver Activity- eller Fragment-kontext för registrering. Använd ViewModel endast för att lagra tillstånd och skapa launchern i Activity eller Fragment och skicka resultatet till ViewModel.

Vilken minsta SDK krävs för Activity Result API?

Activity Result API är tillgängligt från biblioteket activity-ktx 1.2.0. Minsta SDK — API Level 14 (Android 4.0), men de flesta kontrakt fungerar endast på API Level 19+.

Vad händer om launch anropas två gånger innan resultatet tas emot?

Upprepat anrop av launch före slutförandet av den första operationen kommer att ignoreras. Activity Result API stöder inte parallella starter — vänta på callback från den första operationen före ett nytt anrop.

Vad ska jag ersätta onActivityResult med i gammal kod?

Migrering görs genom att ersätta anropet startActivityForResult med registerForActivityResult med motsvarande Contract. Ta bort onActivityResult och hantera resultatet i launcherns callback. Google tillhandahåller en migreringsguide i Android Developers-dokumentationen.

Fungerar ActivityResultLauncher med bibliotek som ML Kit eller Barcode Scanner?

Ja, många bibliotek stöder integration via ActivityResultContracts. Till exempel använder ML Kit Barcode Scanner StartIntentSenderForResult för att starta skannern. Kontrollera dokumentationen för det specifika biblioteket.

Sammanfattning

  • ActivityResultLauncher — modernt typsäkert API istället för föråldrade startActivityForResult
  • Contract definierar typen av in- och utdata, eliminerar manuell matchning av requestCode
  • Registrering sker i initieringsfasen, resultat levereras garanterat via callback
  • Inbyggda kontrakt täcker kamera, galleri, behörigheter, dokument och kontakter
  • Jetpack Compose använder rememberLauncherForActivityResult för att arbeta med API:et
  • Anpassade Contract möjliggör återanvändning av startlogik mellan komponenter
  • API bevarar tillstånd vid konfigurationsändringar via SavedStateRegistry

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också