StartActivityForResult está obsoleto!
Avalie esse Artigo
O Android tem estado na borda da evolução por um tempo recentemente, com atualizações para
androidx.activity:activity-ktx
para 1.2.0
. Ele depreciou startActivityForResult
em favor de registerForActivityResult
.Foi um dos primeiros fundamentos que qualquer desenvolvedor Android aprendeu e a espinha dorsal da maneira de comunicação do Android entre dois componentes. O design da API era simples o suficiente para ser iniciado rapidamente, mas tinha seus contras, como a dificuldade de encontrar o chamador em aplicativos do mundo real (exceto cmd+F no projeto 😂), obter resultados no fragmento, resultados perdidos se o componente é recriado, entra em conflito com o mesmo código de solicitação, etc.
Vamos tentar entender como usar a nova API com alguns exemplos.
Antiga escola:
1 // Caller 2 val intent = Intent(context, Activity1::class.java) 3 startActivityForResult(intent, REQUEST_CODE) 4 5 // Receiver 6 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { 7 super.onActivityResult(requestCode, resultCode, data) 8 if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE) { 9 val value = data?.getStringExtra("input") 10 } 11 }
Novo Caminho:
1 // Caller 2 val intent = Intent(context, Activity1::class.java) 3 getResult.launch(intent) 4 5 // Receiver 6 private val getResult = 7 registerForActivityResult( 8 ActivityResultContracts.StartActivityForResult() 9 ) { 10 if (it.resultCode == Activity.RESULT_OK) { 11 val value = it.data?.getStringExtra("input") 12 } 13 }
Como você deve ter notado,
registerForActivityResult
utiliza dois parâmetros. O primeiro define o tipo de ação/interação necessária (ActivityResultContracts
) e o segundo é uma função de chamada de resposta onde obtemos o resultado.Não mudou muito, não é mesmo? Vamos verificar outro exemplo.
1 //Caller 2 getPreviewImage.launch(null) 3 4 //Receiver 5 private val getPreviewImage = registerForActivityResult(ActivityResultContracts.TakePicture { bitmap -> 6 // we get bitmap as result directly 7 })
O snippet acima é o código completo que obtém uma imagem de visualização da câmera. Não há necessidade de código de solicitação de permissão, pois isso é feito automaticamente para nós!
Outro benefício de usar a nova API é que ela força os desenvolvedores a usar o contrato correto. Por exemplo, com
ActivityResultContracts.TakePicture()
— que retorna a imagem completa — você precisa passar um URI
como parâmetro para launch
, o que reduz o tempo de desenvolvimento e a chance de erros.Esse foi outro problema com o sistema antigo, sem nenhuma implementação limpa disponível, mas a nova API funciona de forma consistente em atividades e fragmentos. Portanto, referenciamos e adicionamos o trecho do exemplo 1 aos nossos fragmentos.
Maneira antiga: .
Com a nova API, isso é possível usando
ActivityResultRegistry
diretamente.1 class MyLifecycleObserver(private val registry: ActivityResultRegistry) : DefaultLifecycleObserver { 2 3 lateinit var getContent: ActivityResultLauncher<String> 4 5 override fun onCreate(owner: LifecycleOwner) { 6 getContent = registry.register("key", owner, GetContent()) { uri -> 7 // Handle the returned Uri 8 } 9 } 10 11 fun selectImage() { 12 getContent.launch("image/*") 13 } 14 } 15 16 class MyFragment : Fragment() { 17 lateinit var observer: MyLifecycleObserver 18 19 override fun onCreate(savedInstanceState: Bundle?) { 20 // ... 21 22 observer = MyLifecycleObserver(requireActivity().activityResultRegistry) 23 lifecycle.addObserver(observer) 24 } 25 26 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 27 val selectButton = view.findViewById<Button>(R.id.select_button) 28 29 selectButton.setOnClickListener { 30 // Open the activity to select an image 31 observer.selectImage() 32 } 33 } 34 }
Encontrei registrarForActivityResult útil e limpo. Alguns dos prós, na minha opinião, são:
- Melhore a legibilidade do código, não é necessário lembrar de pular para
onActivityResult()
depoisstartActivityForResult
. ActivityResultLauncher
retornou doregisterForActivityResult
usado para iniciar componentes, definindo explicitamente o parâmetro de entrada para os resultados desejados.- Foi removido o código padrão para solicitar permissão do usuário.
Espero que isso tenha sido informativo e tenha gostado de lê-lo.