Как стать автором
Обновить

onActivityResult() is deprecated

В этой статье я поделюсь своим опытом перехода от onActivityResult() к Contract.

Краткое резюме статьи на Хабре и личный опыт.

Рассматриваю пример когда существует активити которое задает вопрос хотите ли вы выйти из аккаунта? и все что оно делает для нас это отвечает на вопрос да или нет? Соответственно нам нужно получить одну булиеву переменную.

Как я делал это раньше?

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.exitButton.setOnClickListener {
            startActivityForResult(
                Intent(requireContext(), ExitActivity::class.java),0
            )
        }
 }

 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
      super.onActivityResult(requestCode, resultCode, data)
      if (resultCode == AppCompatActivity.RESULT_OK) {
          if (data?.getBooleanExtra(App.IS_SIGN_OUT, false) == true) {
              // exit fun
          }
      }
  }

Время onActivityResult подходит к концу, сейчас этот метод помечен как deprecated и есть вероятность что в будущих версиях андроид перестанет поддерживаться вовсе.

К нам на помощь спешат так называемые "контракты"!

И так как быстро и безболезненно заменить onActivityResult на свежий и контракт? Все очень просто. Вместо onActivityResult реализуем вот такой функционал:

private val signOutLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                val data = result.data
                if (data?.getBooleanExtra(App.IS_SIGN_OUT, false) == true) {
                    // exit fun
                }
            }
        }

чтобы запустить лаунчер нужно выполнить не хитрую функцию:

signOutLauncher.launch(Intent(requireContext(), ExitActivity::class.java))

Код стал более аккуратным и мы избавились от Deprecated, но это еще не все, есть еще один не плохой плюс в контрактах, мы можем упростить код и сделать его переиспользываемым.

Для этого нужно создать класс контракт.

class SignOutContract : ActivityResultContract<String, Boolean>() {

    override fun createIntent(context: Context, input: String): Intent {
        return Intent(context, PopupActivity::class.java)
            .putExtra("my_key", input)
    }

    override fun parseResult(resultCode: Int, intent: Intent?): Boolean = when {
        resultCode != Activity.RESULT_OK -> false
        else -> intent?.getBooleanExtra(App.IS_SIGN_OUT, false) ?: false
    }

    override fun getSynchronousResult(
        context: Context,
        input: String
    ): SynchronousResult<Boolean>? {
        return if (input.isEmpty()) SynchronousResult(false) else null
    }
}

И собственно инициализация слушателя и вызов этого контракта:

val activityLauncher = registerForActivityResult(SignOutContract()) { result ->
    // используем result (в нашем случаае это Boolean)
    if (result) {
        // exit fun
    }
}
activityLauncher.launch("In yor activity needs string")

Теперь наш код может быть переиспользован и вызов этой активности стал в разы короче!

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.