본문 바로가기
안드로이드(kotlin)

registerForActivityResult 사용 방법과 startActivityForResult가 Deprecated된 이유

by 기계공학 주인장 2023. 1. 7.
반응형

registerForActivityResult 사용과 startActivityForResult가 Deprecated된 이유

  1. startActivityForResult가 Deprecated된 이유를 확인한다
  2. registerForActivityResult을 사용해서 Activity를 열고 닫을 때 callback을 받는다
  3. registerForActivityResult을 사용해서 갤러리를 열고 그림 파일을 받아온다

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


startActivityForResult가 Deprecated된 이유

  • 기존에는 Activity나 Fragment 내부에 startActivityForResult를 정의했다
    • 그 결과 새롭게 연 Activity에서 메모리를 많이 사용할 경우 이전에 열려있던 Activity가 죽어 callBack을 받지 못할 때가 있었음
    • 이를 방지하기 위해 새로운 Activity를 실행하는 부분과 callBack 부분을 분리했다
      • 이것이 registerForActivityResult

registerForActivityResult 구현하기

두 가지 경우를 구현해본다

  1. registerForActivityResult을 사용해서 Activity를 열고 닫을 때 데이터와 Callback을 받고 받은 데이터를 기존의 화면에 출력
  2. registerForActivityResult을 사용해서 갤러리를 열고 선택한 그림 파일을 받아와서 기존의 화면에 출력

registerForActivityResult을 사용해서 Activity 열기

기본적인 레이아웃은 다음과 같이 구성한다

  • FirstFragment.kt
    • Fragment에 있는 Button을 클릭하여 Activity를 연다
    • Callback 시 받아온 데이터를 TextView에 출력한다

  • FirstFragment.kt
// registerForActivityResult는 FirstFragment.kt 전역 부분에 선언하고 정의해야한다
private var resultLauncher = 
	registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            // 전달 받은 String 데이터를 출력
            when {
                !result.data?.getStringExtra("data").isNullOrBlank() -> {
                    binding.textView.text = result.data?.getStringExtra("data")
                    binding.textView2.text = "TestActivity에서 돌아옴"
                }
}

// onViewCreated 안에 정의
binding.openActivity.setOnSingleClickListener {
    val intent = Intent(context, FirstActivity::class.java)
    // 여기서 어떤 Intent를 열지 지정할 수 있다
    // 일반적인 Activity 또는 image Intent 등
    resultLauncher.launch(intent)
}
  • FirstAcitivty.kt
    • registerForActivityResult을 사용하여 연 Activity
    • Close 버튼을 사용해서 닫을 때 Callback과 함께 데이터를 이전 화면에 넘겨준다

// registerForActivityResult는 전역 부분에 정의하고 선언한다
private val resultLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            // 전달 받은 데이터를 로그로 출력
            Timber.d(result.data?.getStringExtra("data"))
        }
    }


// onCreate
binding.button.setOnSingleClickListener {
    // Activity를 종료할 때 데이터를 넘겨줌
    intent.putExtra("data", "FirstActivity에서 전달된 데이터")
    setResult(RESULT_OK, intent)

    finish()
}
  • FirstActivity에서 Close 버튼을 클릭하여 FirstFragment로 돌아왔을 때 결과
    • Callback이 확인됨과 동시에 전달 받은 데이터가 화면에 잘 출력되는 것을 확인할 수 있다

 


registerForActivityResult을 사용해서 갤러리를 열고 그림 파일 받아오기

  • FirstFragment.kt
// 아래의 변수는 전역 변수이다.

private var bookImageBitmap: Bitmap? = null

    // ActivityResultLauncher는 밖에서 선언해야 한다
    private var resultLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                // 전달 받은 String 데이터를 출력
                when {
                    !result.data?.getStringExtra("data").isNullOrBlank() -> {
                        binding.textView.text = result.data?.getStringExtra("data")
                        binding.textView2.text = "TestActivity에서 돌아옴"
                    }
                    // 갤러리에서 돌아온 후 받은 데이터가 있는지 확인
                    result.data?.data != null -> {
                        result.data?.data?.let { uri ->
                            if (result.resultCode == AppCompatActivity.RESULT_OK) {
                                // 사진 데이터를 비트맵으로 변환
                                bookImageBitmap =
                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                                        ImageDecoder.decodeBitmap(
                                            ImageDecoder.createSource(
                                                requireContext().contentResolver, uri
                                            )
                                        )
                                    } else {
                                        MediaStore.Images.Media.getBitmap(
                                            requireContext().contentResolver, uri
                                        )
                                    }
                                Glide.with(requireContext()).load(uri)
                                    .placeholder(R.drawable.ic_bottom_menu_search)
                                    .into(binding.imageView)
                            }
                        }
                    }
                }
            }
        }

// onViewCreated
binding.openImageActivity.setOnSingleClickListener {
    // 갤러리를 여는 Intent를 정의
    val intent = Intent(Intent.ACTION_GET_CONTENT)
    intent.type = "image/*"
    intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NO_HISTORY

    resultLauncher.launch(intent)
}
  • openImageActivity을 사용하여 갤러리를 열었을 때


이렇게 아래의 내용들을 알아봤습니다.

 

registerForActivityResult 사용과 startActivityForResult가 Deprecated된 이유

  1. startActivityForResult가 Deprecated된 이유를 확인한다
  2. registerForActivityResult을 사용해서 Activity를 열고 닫을 때 callback을 받는다
  3. registerForActivityResult을 사용해서 갤러리를 열고 그림 파일을 받아온다
반응형


"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


댓글