ActivityResultLauncher: o que é e como usar

Autor: IT Sectr Publicado: 2026-06-10 Tempo de leitura: 9 min

ActivityResultLauncher é um componente da API Activity Result do Android, apresentado na versão Activity 1.2.0 da biblioteca androidx.activity. Ele substitui os métodos obsoletos startActivityForResult e onActivityResult, que faziam parte do Android SDK desde sua criação. De acordo com Android Developers (2024), a nova API elimina os problemas de acoplamento forte com Activity e a falta de segurança de tipos. ActivityResultLauncher é registrado antecipadamente e usa um Contract para tipagem estrita dos dados de entrada e saída.

Pontos principais

  • ActivityResultLauncher — uma nova API para obter resultados de uma Activity em vez do obsoleto startActivityForResult
  • Contract — um objeto que define o tipo de dados de entrada e saída para um cenário específico
  • Registro é feito através de registerForActivityResult antes de chamar launch
  • Callback é invocado após a Activity de destino terminar com um resultado
  • API disponível para Activity, Fragment e Compose a partir de Activity 1.2.0

O que é ActivityResultLauncher

ActivityResultLauncher é uma classe do pacote androidx.activity.result que fornece um mecanismo type-safe para iniciar uma Activity e receber um resultado. O launcher é criado através do método registerForActivityResult, que aceita dois parâmetros: Contract (descreve os tipos de entrada e saída) e ActivityResultCallback (manipulador de resultado). Após o registro, o launcher está pronto para ser chamado através do método launch.

A diferença chave da API antiga é a separação do registro e da execução. O registro é realizado na fase de inicialização (Activity.onCreate ou Fragment.onCreate), o callback é vinculado ao launcher uma vez e tem a garantia de ser executado quando o resultado retornar. Isso elimina o problema de onActivityResult ser executado em uma ordem inesperada ou em uma Activity destruída.

ActivityResultLauncher suporta todos os cenários que anteriormente eram tratados via onActivityResult: iniciar a câmera, galeria, solicitar contatos, permissões e Activities personalizadas. Além disso, a API é extensível: os desenvolvedores podem criar Contracts personalizados para cenários específicos de troca de dados entre Activities.

Por que Activity Result API substituiu startActivityForResult

startActivityForResult fez parte do Android SDK desde API Level 1 (2008) e continuou sendo a principal forma de obter um resultado de uma Activity por mais de 12 anos. No entanto, este método tinha deficiências fundamentais que o Google resolveu no Activity Result API. Vamos ver os principais problemas e como a nova API os soluciona.

Problema 1: Acoplamento forte com Activity

O método startActivityForResult está vinculado a Activity e Fragment através de requestCode — um número inteiro arbitrário passado para onActivityResult. O desenvolvedor manualmente associava o código à operação iniciada, levando a erros na reutilização de código e herança. ActivityResultLauncher elimina completamente requestCode: o callback é vinculado a um launcher específico no momento do registro e só é invocado para ele.

Problema 2: Perda do resultado ao girar a tela

Durante mudanças de configuração (rotação de tela, mudança de idioma), a Activity era recriada e onActivityResult podia não ser executado — o callback era perdido. O Activity Result API salva e restaura automaticamente o estado do launcher através do SavedStateRegistry, garantindo que o resultado seja recebido mesmo após a recriação da Activity.

Problema 3: Falta de segurança de tipos

A API antiga passava o resultado através de Intent com Bundle, onde chaves e tipos de dados não eram verificados pelo compilador. O Activity Result API usa Contract — uma interface genérica que define o tipo de dados de entrada (I) e o tipo de resultado (O). Erros de incompatibilidade de tipos são detectados em tempo de compilação, não em tempo de execução.

CaracterísticastartActivityForResultActivityResultLauncher
RequestCodeGerenciamento manual necessárioAutomático, não necessário
Segurança de tiposNãoContract genérico
Salvar ao girarPerdidoSavedStateRegistry
API mínimaAPI Level 1Activity 1.2.0
Uso no ComposeNão suportadorememberLauncherForActivityResult

Principais contratos do Activity Result API

Contract é a interface ActivityResultContract<I, O>, que define como iniciar uma Activity e como interpretar o resultado. O Google fornece um conjunto de contratos integrados para cenários típicos que cobrem a maioria das necessidades do desenvolvedor.

StartIntentSenderForResult

StartIntentSenderForResult — um contrato básico para iniciar IntentSender. Usado em cenários de sistema, por exemplo ao autorizar via Google Sign-In ou fazer pagamentos via Google Pay. O parâmetro de entrada é PendingIntent, a saída é ActivityResult com código e Intent.

RequestMultiplePermissions

RequestMultiplePermissions — um contrato para solicitar várias permissões simultaneamente no Android 6.0+. O parâmetro de entrada é um array de String com nomes de permissões, a saída é Map<String, Boolean> com o resultado de cada solicitação. Anteriormente isso exigia análise manual em onRequestPermissionsResult com correspondência de códigos de solicitação.

TakePicture e TakeVideo

TakePicture — um contrato para tirar uma foto através da câmera do sistema. A entrada é um Uri para salvar a imagem, a saída é Boolean (sucesso). TakeVideo funciona de forma semelhante com vídeo. Esses contratos substituem o obsoleto MediaStore.ACTION_IMAGE_CAPTURE com comportamento instável em diferentes dispositivos.

GetContent e OpenDocument

GetContent — um contrato para selecionar conteúdo através do seletor do sistema. A entrada é um tipo MIME (por exemplo, image/*), a saída é um Uri do arquivo selecionado. OpenDocument difere por suportar seleção múltipla e filtragem por tipos de documento. Ambos os contratos funcionam através de SAF (Storage Access Framework).

CreateDocument e OpenDocumentTree

CreateDocument — um contrato para criar um novo documento através do diálogo do sistema. O usuário escolhe um nome e uma pasta, o sistema retorna um Uri para escrita. OpenDocumentTree fornece acesso a um diretório completo — o usuário seleciona uma pasta e o aplicativo recebe um tree-uri para ler e escrever todos os arquivos dentro dela.

Uso em Activity e Fragment

O padrão básico para usar ActivityResultLauncher no Android clássico consiste em duas etapas: registro através de registerForActivityResult na inicialização e chamada de launch em resposta a uma ação do usuário. Vamos ver um exemplo típico de seleção de uma imagem da galeria.

Registro e execução em Activity

Registre o launcher no onCreate da Activity — isso garante que o callback esteja pronto antes de qualquer chamada possível. Nunca registre um launcher imediatamente antes de executá-lo — isso viola o contrato da API e pode levar à perda do resultado ao recriar a 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/*")
    }
}

Uso em Fragment

Em um Fragment, o registro é feito em onCreate, onAttach ou inicialização em onCreateView. O FragmentActivity passa o launcher através da Activity pai, então o resultado é processado dentro do Fragment, não na Activity. Isso melhora o encapsulamento em comparação com onActivityResult, onde todos os resultados de todos os Fragments eram reunidos em um único método da Activity.

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

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

ActivityResultLauncher no Jetpack Compose

Jetpack Compose fornece uma função composable especial para Activity Result API — rememberLauncherForActivityResult. Ao contrário da abordagem clássica, no Compose o launcher é criado como um objeto vinculado ao ciclo de vida do composable através de remember. Isso permite usar o Activity Result API completamente em estilo declarativo sem acesso direto a Activity ou Fragment.

rememberLauncherForActivityResult

rememberLauncherForActivityResult aceita um Contract e um callback, retornando um ActivityResultLauncher. O launcher é preservado durante a recomposição e automaticamente limpo ao sair da composição. A chamada de launch ocorre em resposta a um evento — por exemplo, um clique em botão ou mudança de estado.

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

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

Gerenciamento de permissões no Compose

Solicitações de permissão no Compose também são feitas através de rememberLauncherForActivityResult com o contrato RequestPermission ou RequestMultiplePermissions. O Google recomenda usar accompanist-permissions, mas internamente ele também usa o Activity Result API. Para controlar o estado das permissões, é conveniente armazenar o estado em remember ou ViewModel.

Erros comuns e melhores práticas

Activity Result API eliminou muitos problemas da abordagem antiga, mas o uso inadequado pode levar a novos tipos de erros. Vamos ver os problemas mais comuns e como evitá-los.

Erro: registro dentro de uma lambda ou corrotina

O registro do launcher deve ser feito durante a inicialização do componente — no onCreate da Activity ou inicializador do Fragment. Se você registrar o launcher dentro de uma lambda, callback ou corrotina, ao recriar a Activity o registro pode ser feito novamente e o launcher antigo perderá a conexão com o resultado.

Erro: registrar vários launchers com a mesma chave

Cada launcher recebe uma chave única para salvar o estado. Se você registrar dois launchers com o mesmo Contract em um componente, o SavedStateRegistry pode sobrescrever o estado de um com o do outro. O Android Studio avisa sobre isso através da regra lint UnnecessaryRegisterForActivityResult, mas é melhor controlar a exclusividade manualmente.

Melhor prática: sempre tratar resultado nulo

O usuário pode cancelar a ação — pressionar o botão voltar do sistema, minimizar o aplicativo ou mudar para outro aplicativo. Neste caso, o callback receberá null ou ActivityResult com RESULT_CANCELED. Sempre verifique se o resultado é null antes de usá-lo para evitar NullPointerException.

Melhor prática: Contracts personalizados para lógica reutilizável

Se seu aplicativo inicia frequentemente cenários semelhantes — por exemplo, selecionar um contato e retornar nome e telefone — crie um Contract personalizado. Isso melhora a legibilidade do código e permite alterações centralizadas na lógica de inicialização e tratamento de resultados.

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

Perguntas frequentes

Pode-se usar ActivityResultLauncher no ViewModel?

Não — ActivityResultLauncher requer um contexto de Activity ou Fragment para registro. Use ViewModel apenas para armazenar estado, e crie o launcher na Activity ou Fragment e passe o resultado para o ViewModel.

Qual é o SDK mínimo necessário para Activity Result API?

Activity Result API está disponível a partir da biblioteca activity-ktx 1.2.0. O SDK mínimo é API Level 14 (Android 4.0), mas a maioria dos contratos funciona apenas em API Level 19+.

O que acontece se launch for chamado duas vezes antes de receber um resultado?

Uma chamada repetida de launch antes da primeira operação terminar será ignorada. O Activity Result API não suporta execuções paralelas — aguarde o callback da primeira operação antes de fazer uma nova chamada.

Como substituir onActivityResult em código antigo?

A migração é feita substituindo a chamada startActivityForResult por registerForActivityResult com o Contract apropriado. Remova onActivityResult e manipule o resultado no callback do launcher. O Google fornece um guia de migração na documentação do Android Developers.

ActivityResultLauncher funciona com bibliotecas como ML Kit ou Barcode Scanner?

Sim, muitas bibliotecas suportam integração através de ActivityResultContracts. Por exemplo, ML Kit Barcode Scanner usa StartIntentSenderForResult para iniciar o scanner. Verifique a documentação da biblioteca específica.

Resumo

  • ActivityResultLauncher — uma API moderna type-safe que substitui o obsoleto startActivityForResult
  • Contract define os tipos de dados de entrada e saída, eliminando a correspondência manual de requestCode
  • Registro é feito na inicialização, o resultado é entregue garantidamente através de callback
  • Contratos integrados cobrem câmera, galeria, permissões, documentos e contatos
  • Jetpack Compose usa rememberLauncherForActivityResult para trabalhar com a API
  • Contracts personalizados permitem reutilizar a lógica de execução entre componentes
  • API preserva estado durante mudanças de configuração através de SavedStateRegistry

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também