본문 바로가기
ANDROID/Android 개발 이슈 & 해결

[Android] Activity Result API : Fragment에서 registerForActivityResult()

by 주 녕 2021. 8. 17.
728x90

2019년 클론 프로젝트 강의를 보면서 진행하다보니 deprecated를 정말 많이 마주치는 것 같습니다ㅠㅠ

오늘은 지난 포스팅에 이어 Fragment에서 Activity Result API를 사용하는 방법에 대해 포스팅해보려고 합니다!

우선 하고자 하는 것은 아래 화면과 같이 프로필 이미지를 누르면 이미지를 선택할 수 있는 디렉토리로 넘어가는 것입니다.

우선 Activity Result API에 대해 설명한 지난 포스팅을 보는 것을 추천하겠습니다..ㅎㅎ

 

[Android] Activity Result API : startActivityForResult() deprecated 해결

안드로이드 인스타그램 클론 프로젝트를 진행하던 중에 새로운 문제를 만났다. 오랜만에 안드로이드 스튜디오와 코틀린을 최신 버전으로 업데이트 받았는데, startActivityForResult() 메소드가 depreca

junyoung-developer.tistory.com

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        _binding = FragmentUserBinding.inflate(inflater, container, false)
        ...
        
        private val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
            if (it.resultCode == Activity.RESULT_OK) {
                var imageUrl = it.data?.data
                ...
            }
        }
        
        // User's Profile Image Setting
        binding.userImage.setOnClickListener {
            var photoPickerIntent = Intent(Intent.ACTION_PICK)
            photoPickerIntent.type = "image/*"
            startForResult.launch(photoPickerIntent)
        }
        return binding.root
    }

내가 먼저 작성했던 코드는 위와 같습니다. 지난 포스팅에서는 Activity에서 registerForActivityResult()를 사용한 예시를 보여줬는데 Fragment에서도 사용법은 같은 것을 확인할 수 있습니다.

 

 

🔺 BUT, 아무 생각없이 onCreateView에 모든 것을 작성했더니 아래와 같은 오류가 발생했습니다...

Fragments must call registerForActivityResult() before they are created (i.e. initialization, onAttach(), or onCreate()).

Fragment는 생성되기 전(즉, initialization, onAttach(), onCreate())에 registerForActivityResult()를 호출해야 한다고 아주 친절하게 설명해주고 있습니다.  그 이유는 이전 포스팅에서도 올린 것처럼 공식 문서에서 명시하고 있었는데 그때는 무슨 말인지 잘 이해를 하지 못하고 있었는데, 이번 기회로 이해를 했답니다.

 

공식문서에 명시된 이유

For this reason, the Activity Result APIs decouple the result callback from the place in your code where you launch the other activity. As the result callback needs to be available when your process and activity are recreated, the callback must be unconditionally registered every time your activity is created, even if the logic of launching the other activity only happens based on user input or other business logic.

결과를 얻기 위해 Activity를 시작할 때, 메모리 부족으로 인해 프로세스와 Activity가 소멸될 수 있다. 따라서 Activity Result API는 다른 Activity를 실행하는 코드에서 결과 콜백을 분리한다.  프로세스 및 작업을 다시 생성할 때 결과 콜백을 사용할 수 있어야 하므로 다른 작업을 시작하는 로직이 사용자 입력 또는 다른 비즈니스 로직에 따라서만 발생하더라도 작업이 생성될 때마다 콜백을 무조건 등록해야 합니다.
 

활동에서 결과 가져오기  |  Android 개발자  |  Android Developers

개발자 앱 내의 활동이든 다른 앱의 활동이든 다른 활동을 시작하는 것이 단방향 작업일 필요는 없습니다. 다른 활동을 시작하고 다시 결과를 받을 수도 있습니다. 예를 들어, 앱에서 카메라 앱

developer.android.com

 

 

🧐😎 initialization으로 문제 해결!

class UserFragment : Fragment() {

    ...
    private val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        ...
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        ...

        // User's Profile Image Setting
        binding.userImage.setOnClickListener {
            var photoPickerIntent = Intent(Intent.ACTION_PICK)
            photoPickerIntent.type = "image/*"
            startForResult.launch(photoPickerIntent)
        }
        
        ...
    }

 

728x90

댓글