ActivityResultLauncher: co to je a jak používat

Autor: IT Sectr Publikováno: 2026-06-10 Doba čtení: 9 min

ActivityResultLauncher je komponenta Android Activity Result API, představená ve verzi Activity 1.2.0 knihovny androidx.activity. Nahrazuje zastaralé metody startActivityForResult a onActivityResult, které byly součástí Android SDK od jeho vzniku. Podle Android Developers (2024) nové API odstraňuje problémy těsného propojení s Activity a chybějící typové bezpečnosti. ActivityResultLauncher se registruje předem a používá Contract pro striktní typování vstupních a výstupních dat.

Hlavní body

  • ActivityResultLauncher — nové API pro získání výsledku z Activity namísto zastaralého startActivityForResult
  • Contract — objekt, který definuje typ vstupních a výstupních dat pro konkrétní scénář
  • Registrace se provádí pomocí registerForActivityResult před voláním launch
  • Callback — je volán po dokončení cílové Activity s výsledkem
  • API dostupné pro Activity, Fragment a Compose od Activity 1.2.0

Co je ActivityResultLauncher

ActivityResultLauncher je třída z balíčku androidx.activity.result, která poskytuje typově bezpečný mechanismus pro spouštění Activity a získávání výsledku. Launcher je vytvořen pomocí metody registerForActivityResult, která přijímá dva parametry: Contract (popisuje vstupní a výstupní typy) a ActivityResultCallback (zpracovatel výsledku). Po registraci je launcher připraven k volání pomocí metody launch.

Klíčový rozdíl oproti starému API je oddělení registrace a spouštění. Registrace probíhá ve fázi inicializace (Activity.onCreate nebo Fragment.onCreate), callback je navázán na launcher jednou a garantovaně se aktivuje při vrácení výsledku. To odstraňuje problém, kdy se onActivityResult aktivoval v neočekávaném pořadí nebo na zničené Activity.

ActivityResultLauncher podporuje všechny scénáře, které byly dříve zpracovávány přes onActivityResult: spouštění kamery, galerie, žádost o kontakty, oprávnění a vlastní Activity. Kromě toho je API rozšiřitelné: vývojář může vytvářet vlastní Contract pro specifické scénáře výměny dat mezi Activity.

Proč Activity Result API nahradilo startActivityForResult

startActivityForResult byl součástí Android SDK od verze API Level 1 (2008) a zůstal hlavním způsobem získávání výsledku z Activity po více než 12 let. Tato metoda však měla zásadní nedostatky, které Google odstranil v Activity Result API. Podívejme se na hlavní problémy a jak je nové API řeší.

Problém 1: těsné propojení s Activity

Metoda startActivityForResult je spojena s Activity a Fragment prostřednictvím requestCode — libovolného celého čísla, které je předáno do onActivityResult. Vývojář ručně přiřazoval kód ke spuštěné operaci, což vedlo k chybám při opětovném použití kódu a dědičnosti. ActivityResultLauncher zcela odstraňuje requestCode: callback je navázán na konkrétní launcher ve fázi registrace a je volán pouze pro něj.

Problém 2: ztráta výsledku při otáčení obrazovky

Při změnách konfigurace (otočení obrazovky, změna jazyka) byla Activity znovu vytvořena a onActivityResult se nemusel aktivovat — callback se ztratil. Activity Result API automaticky ukládá a obnovuje stav launcheru pomocí SavedStateRegistry, což garantuje přijetí výsledku i po znovuvytvoření Activity.

Problém 3: chybějící typová bezpečnost

Staré API předávalo výsledek přes Intent s Bundle, kde klíče a datové typy nebyly kontrolovány kompilátorem. Activity Result API používá Contract — generické rozhraní, které definuje typ vstupních dat (I) a typ výsledku (O). Chyby typové neshody jsou detekovány ve fázi kompilace, nikoli za běhu.

VlastnoststartActivityForResultActivityResultLauncher
RequestCodeVyžaduje ruční správuAutomatický, není vyžadován
Typová bezpečnostNeGeneric Contract
Uložení při otočeníZtrácí seSavedStateRegistry
Minimální APIAPI Level 1Activity 1.2.0
Použití v ComposeNení podporovánorememberLauncherForActivityResult

Hlavní kontrakty Activity Result API

Contract je rozhraní ActivityResultContract<I, O>, které definuje, jak spustit Activity a jak interpretovat výsledek. Google poskytuje sadu vestavěných kontraktů pro typické scénáře, pokrývající většinu potřeb vývojáře.

StartIntentSenderForResult

StartIntentSenderForResult je základní kontrakt pro spouštění IntentSender. Používá se v systémových scénářích, například při autentizaci přes Google Sign-In nebo při platbě přes Google Pay. Vstupní parametr — PendingIntent, výstup — ActivityResult s kódem a Intent.

RequestMultiplePermissions

RequestMultiplePermissions je kontrakt pro žádost o více oprávnění současně v Android 6.0+. Vstupní parametr — pole String s názvy oprávnění, výstup — Map<String, Boolean> s výsledkem každé žádosti. Dříve to vyžadovalo ruční parsování v onRequestPermissionsResult s přiřazováním kódů žádostí.

TakePicture a TakeVideo

TakePicture je kontrakt pro fotografování přes systémový fotoaparát. Vstup — Uri, kam uložit snímek, výstup — Boolean (úspěch). TakeVideo funguje podobně s videem. Tyto kontrakty nahrazují zastaralý MediaStore.ACTION_IMAGE_CAPTURE s nestabilním chováním na různých zařízeních.

GetContent a OpenDocument

GetContent je kontrakt pro výběr obsahu přes systémový výběr. Vstup — MIME typ (např. image/*), výstup — Uri vybraného souboru. OpenDocument se liší podporou vícenásobného výběru a filtrováním podle typů dokumentů. Oba kontrakty fungují přes SAF (Storage Access Framework).

CreateDocument a OpenDocumentTree

CreateDocument je kontrakt pro vytvoření nového dokumentu přes systémové dialogové okno. Uživatel vybere název a složku, systém vrátí Uri pro zápis. OpenDocumentTree poskytuje přístup k celému adresáři — uživatel vybere složku a aplikace získá tree-uri pro čtení a zápis všech souborů uvnitř.

Použití v Activity a Fragment

Základní vzor použití ActivityResultLauncher v klasickém Androidu se skládá ze dvou kroků: registrace pomocí registerForActivityResult ve fázi inicializace a volání launch jako odpověď na akci uživatele. Podívejme se na typický příklad výběru obrázku z galerie.

Registrace a spuštění v Activity

Zaregistrujte launcher v onCreate Activity — to garantuje, že callback bude připraven před jakýmkoli možným voláním. Nikdy neregistrujte launcher bezprostředně před spuštěním — to porušuje kontrakt API a může vést ke ztrátě výsledku při znovuvytvoření 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/*")
    }
}

Použití ve Fragment

Ve Fragment se registrace provádí v onCreate, onAttach nebo inicializaci v onCreateView. FragmentActivity předává launcher přes rodičovskou Activity, takže výsledek je zpracováván uvnitř Fragment, nikoli v Activity. To zlepšuje zapouzdření ve srovnání s onActivityResult, kde byly všechny výsledky ze všech Fragment shromažďovány v jedné metodě Activity.

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

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

ActivityResultLauncher v Jetpack Compose

Jetpack Compose poskytuje speciální funkcionalitu composable pro Activity Result API — rememberLauncherForActivityResult. Na rozdíl od klasického přístupu je v Compose launcher vytvořen jako objekt navázaný na životní cyklus composable přes remember. To umožňuje používat Activity Result API plně deklarativním stylem bez přímého přístupu k Activity nebo Fragment.

rememberLauncherForActivityResult

rememberLauncherForActivityResult přijímá Contract a callback, vrací ActivityResultLauncher. Launcher je zachován při rekompozici a automaticky čištěn při opuštění kompozice. Volání launch nastává jako reakce na událost — například stisknutí tlačítka nebo změna stavu.

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

    Button(onClick = { launcher.launch("image/*") }) {
        Text("Vybrat fotografii")
    }
}

Zpracování oprávnění v Compose

Žádost o oprávnění v Compose se také provádí pomocí rememberLauncherForActivityResult s kontraktem RequestPermission nebo RequestMultiplePermissions. Google doporučuje používat accompanist-permissions, ale pod kapotou také používá Activity Result API. Pro kontrolu stavu oprávnění je vhodné ukládat stav do remember nebo ViewModel.

Typické chyby a osvědčené postupy

Activity Result API odstranilo mnoho problémů starého přístupu, ale jeho nesprávné použití může vést k novým typům chyb. Podívejme se na nejčastější problémy a způsoby, jak se jim vyhnout.

Chyba: registrace uvnitř lambdy nebo korutiny

Registrace launcheru musí proběhnout při inicializaci komponenty — v onCreate Activity nebo inicializátoru Fragment. Pokud registrujete launcher uvnitř lambdy, callbacku nebo korutiny, při znovuvytvoření Activity může být registrace provedena znovu a starý launcher ztratí spojení s výsledkem.

Chyba: registrace více launcherů se stejným klíčem

Každý launcher získává jedinečný klíč pro ukládání stavu. Pokud zaregistrujete dva launchery se stejným Contract v jedné komponentě, SavedStateRegistry může přepsat stav jednoho druhým. Android Studio na to upozorňuje pomocí lint pravidla UnnecessaryRegisterForActivityResult, ale je lepší kontrolovat jedinečnost ručně.

Osvědčený postup: vždy zpracovávat null výsledek

Uživatel může zrušit akci — stisknout systémové tlačítko zpět, minimalizovat aplikaci nebo přepnout na jinou aplikaci. V tomto případě callback obdrží null nebo ActivityResult s RESULT_CANCELED. Vždy kontrolujte výsledek na null před použitím, abyste předešli NullPointerException.

Osvědčený postup: vlastní Contract pro znovupoužitelnou logiku

Pokud vaše aplikace často spouští podobné scénáře — například výběr kontaktu s vrácením jména a telefonu — vytvořte si vlastní Contract. To zlepšuje čitelnost kódu a umožňuje centrálně měnit logiku spouštění a zpracování výsledku.

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

Často kladené otázky

Lze použít ActivityResultLauncher ve ViewModel?

Ne — ActivityResultLauncher vyžaduje kontext Activity nebo Fragment pro registraci. Používejte ViewModel pouze pro ukládání stavu a launcher vytvářejte v Activity nebo Fragment a výsledek předejte do ViewModel.

Jaké minimální SDK je vyžadováno pro Activity Result API?

Activity Result API je dostupné od knihovny activity-ktx 1.2.0. Minimální SDK — API Level 14 (Android 4.0), ale většina kontraktů funguje pouze na API Level 19+.

Co se stane, když je launch volán dvakrát před obdržením výsledku?

Opakované volání launch před dokončením první operace bude ignorováno. Activity Result API nepodporuje paralelní spouštění — počkejte na callback z první operace před novým voláním.

Čím nahradit onActivityResult ve starém kódu?

Migrace se provádí nahrazením volání startActivityForResult za registerForActivityResult s odpovídajícím Contract. Odstraňte onActivityResult a zpracovávejte výsledek v callbacku launcheru. Google poskytuje migrační příručku v dokumentaci Android Developers.

Funguje ActivityResultLauncher s knihovnami jako ML Kit nebo Barcode Scanner?

Ano, mnoho knihoven podporuje integraci přes ActivityResultContracts. Například ML Kit Barcode Scanner používá StartIntentSenderForResult ke spuštění skeneru. Zkontrolujte dokumentaci konkrétní knihovny.

Shrnutí

  • ActivityResultLauncher — moderní typově bezpečné API namísto zastaralého startActivityForResult
  • Contract definuje typ vstupních a výstupních dat, eliminuje ruční přiřazování requestCode
  • Registrace probíhá ve fázi inicializace, výsledek je garantovaně doručen přes callback
  • Vestavěné kontrakty pokrývají kameru, galerii, oprávnění, dokumenty a kontakty
  • Jetpack Compose používá rememberLauncherForActivityResult pro práci s API
  • Vlastní Contract umožňují znovupoužití logiky spouštění mezi komponentami
  • API ukládá stav při změnách konfigurace přes SavedStateRegistry

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také