안드로이드(kotlin)

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

기계공학 주인장 2023. 1. 7. 11:02
반응형

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을 사용해서 갤러리를 열고 그림 파일을 받아온다
반응형