1 분 소요

기존의 startActivityForResult

안드로이드에서 일반적으로 Activity를 전환하기 위해서는 startActivity() 를 사용하지만 화면 전환 이후에 해당 Activity에서의 결과값을 전달 받기 위해서는 startActivityForResult()onActivityResult() 를 사용 하였다.

// 두 번째 인자인 requestCode는 어떤 Activity인지 식별해주는 값
startActivityForResult(Intent(this@FromActivity, ToActivity.class.java), 101)

setResult()

해당하는 ToActivity의 종료 시점에 작성하여 Activity가 종료되면 해당 메서드를 통해 호출한 Activity에 데이터를 되돌려 줄 수 있다.

// 호출당한 ToActivity
val intent = Intent()
intent.putExtra("result", "some data");
setResult(RESULT_OK, intent)
finish()

onActivityResult()


// 결과를 받는 FromActivity
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == 101) {
        if (resultCode == Activity.RESULT_OK) {
            val result = data?.getStringExtra("result")
            ...
        }
    }
}

새로운 API

해당하는 startActivityForResult API는 2020년 5월에 deprecated 되었다고 한다. 구글에서는 새로운 AndroidX Activity와 Fragment에 도입된 Activity Result API 사용을 적극 권장한다.

deprecated 된 이유와 새로운 API

안드로이드에서 메모리 부족으로 인해 프로세스와 Activity가 사라질 수 있다. 기존의 방식은 같은 곳에서 startActivityForResultonActivityResult에서 콜백을 처리해야 했다.

만약 Activity가 종료되고 다시 만들어 진다면 Activity에게 Result를 기다린다고 다시 알려주어야 한다. 따라서 호출과 콜백을 따로 분리해서 만들어 주어야 하는데 이에 대한 역할을 해주는 것이 ActivityResultLauncher 이다.

registActivityForResult() 메소드는 ActivityResultContract 및 ActivityResultCallback 을 가져와서 다른 활동을 실행하는 데 사용할 ActivityResultLauncher를 반환해 준다.

registActivityForResult()는 콜백을 등록해 주는 역할을 해주어 Activity가 종료되었다가 다시 생성이 되어도 결과를 기다리고 있다고 알려줄 수 있다.

기존의 방식

  • A -> B를 호출하다 A가 종료된다.
  • B에서는 setResult()로 결과값을 반환한다.
  • 다시 돌아와서 보니 A가 종료 되었다가 다시 생성되어 결과값을 요청한지 모름

새로운 API

  • A -> B를 호출하다 A가 종료된다.
  • B에서는 setResult()로 결과값을 반환한다.
  • A가 다시 생성되도 registForActivityResult() 메소드가 다시 콜백을 등록해 주기 떄문에 결과값을 받아 올 수 있다.
// 호출하는 부분 기존
startActivityForResult(Intent(this@FromActivity, ToActivity.class.java), 101)
// 새로운 API -> launch() 로 시작
result.launch(Intent(this@FromActivity, ToActivity::class.java))

// Contract 및 결과를 받기 위한 Callback 등록 
private val result = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()) {
    if (it.resultCode == Activity.RESULT_OK) {
        val intent = it.data
        val data = intent?.getStringExtra("result")
        ...
    }
}

기존에서와 다르게 result라는 ActivityResultLauncher 를 생성하여 콜백을 등록한다. 함수의 첫 번째 인자인 Contract는 현재 결과를 받을 Activity를 실행하는 함수인 ActivityResultContracts.StartActivityForResult()를 등록한다. launch()를 통하여 이동한 Activity에서는 동일하게 setResult() 함수를 그대로 사용하면 된다.

📍requestCode가 필요없는 이유

  • 원하는 Activity의 요청 마다 registForAcitivtyResult를 실행하여 콜백을 분리하였기 때문에 기존처럼 Acitivity를 구분할 필요가 없어졌다.

References

맨 위로 이동 ↑

댓글남기기