Fragment의 onActivityResult로 결과 받기

안드로이드 어플리케이션은 컴포넌트로 구성된다. ActivityManager는 컴포넌트들 사이에 Intent 형태의 데이터를 주고 받을 수 있게 해준다. 액티비티 간 데이터를 주고 받을 때 용이하도록 액티비티와 프레그먼트는 startActivity(), startActivityForResult(), onActivityResult() 메소드를 제공한다. 여기서는 프레그먼트의 onActivityResult()에 대해 살펴보자.

결론부터 말하면, 프레그먼트의 onActivityResult()도 다른 액티비티에서 데이터를 받을 수 있다. 다른 특별한 처리 없이 말이다.

지금 인터넷을 보면 액티비티의 onActivityResult()만 다른 액티비티나 프레그먼트에서 startActivityForResult()통해 요청한 작업의 결과를 받을 수 있다고 한다. 그리고, 프레그먼트의 onActivityResult()에 데이터를 전달하는 다양한 방법들(FragmentManager를 통한 프레그먼트의 onActivityResult() 명시적 호출, 이벤트 버스 사용 등)을 소개한다.  안드로이드가 이상하게 동작한다는 불만도 잊지 않는다.

아마도 이런 오해는 액티비티 간 데이터가 어떻게 전달되는지 이해하지 못해 발생한 것 같다. 액티비티가 데이터를 주고 받는 규칙을 살펴보자.

  • 액티비티의 onActivityResult()는 액티비티나 프레그먼트 둘 중 어느 것의 결과든 받는다.
  • 프레그먼트의 onActivityResult()는 프레그먼트의 startActivityForResult()를 통해 호출한 액티비티에서만 결과를 받는다.
  • 프레그먼트는 액티비티의 onActivityResult()가 호출 된 후 호출 된다. 정확히, 프레그먼트의 onActivityResult()는 액티비티의 onActivityResult() 코드 내부에서 호출된다.

그러므로, 아래와 같이 사용하면 결과를 받을 수 없다.

  • 프레그먼트 안에서 (예를 들면, getActivity() 같은 메소드를 통해 얻은) 액티비티 객체의 startActivityForResult()를 호출한다. 이 때는, 액티비티의 startActivityForResult()를 호출한 것이므로 액티비티로만 결과가 전달된다.
  • 내 액티비티에서 onActivityResult() 메소드를 오버라이드 한 후, 이 메소드에서 super.onActicityResult()로 결과를 전달하지 않고 데이터를 소진한다. 프레그먼트는 데이터를 액티비티의 onActivityResult()를 통해 전달받기 때문에 super.onActivityResult()로 값을 전달하지 않으면 프레그먼트에도 전달되지 않는다.

대신, 아래와 같이 사용해야 결과를 받을 수 있다.

  • Activity.startActivityForResult()가 아닌Fragment.startActivityForResult()를 사용해 호출한다.

프레그먼트 속 onActivityResult()로 결과가 오지 않아 힘들어 했다면, 지금이라도 바르게 사용해 보자.

그 밖에

  • 사실 액티비티에서 프레그먼트에 결과를 전달하는 과정은 인터넷에 알려진 FragmentManager를 이용한 자식 프레그먼트들의 onActivityResult() 명시적 호출과 크게 다르지 않다.
  • 프레그먼트를 추가할 때 건넨 tag를 이용해 프레그먼트를 찾기라도 한다면, 이 태그를 통해 액티비티와 프레그먼트가 강결합하게 되어 더 나쁘다.
  • 액티비티-프레그먼트A-프레그먼트B 순으로 포함하는 계층 구조라도, 프레그먼트 B에서 호출한 액티비티의 결과를 프레그먼트 A가 받지는 않는다. 액티비티에서 각 프레그먼트에 결과 값을 전달한다.
  • Fragment의 공식 문서를 보면 프레그먼트의 onActivityResult()에 대한 설명이 단촐하다. ‘액티비티의 onActivityResult()와 관련이 있다.’라고만 언급이 되어있다.
  • 액티비티의 onActivityResult()는 스코프(scope)가 protected이고, 프래그먼트의 그 것은 public이다.

참조

14 thoughts on “Fragment의 onActivityResult로 결과 받기”

    1. 그림같은 것으로 좀 더 친절하게 설명했어야 하는데, 제 생각을 정리해 두는 수준으로 적다보니 어려운 글이 되어버렸나 봅니다. 다음에 그림 추가해 볼께요.

  1. 참나 결국엔 못사용한다는거아님? 낚였네 뭐하는거지진짜 ㅡㅡ 짜증지대로난다

    1. 다시 한번 잘 읽어보시면, 안드로이드에서 지원하는 대로 쓰면 따로 커스텀하지 않아도 된다는 글입니다.

    2. 이해를 못했으면 이해를 못했다고 작성자분께 정중히 여쭤보시길..
      내용은 전혀 문제가 없고 좋은 내용인데 자신의 무지를 탓하세요

  2. 뭐라는거야 제목은 받기라고해놓고선 결국엔 못받는다는거잖아 장난?

  3. 댓글 입력도 안되네 뭐냐진짜 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

  4. 설명 감사합니다. 고민하던부분이 일부해결되었네요. 추가로 질문드리자면 프레그먼트에서 호출할때 Fragment.startActivityForResult() 로선언한다면 프레그먼트가 속해있는 부모 액티비티에 별도의 코드없이 프레그먼트 내부의 onActivityResult()에서 받는다는것이 맞는지요??

  5. FragmentManager 를 사용하거나 Custom Event Class 를 사용한다는 다른 글과 다른 유용한 글이네요.
    몇몇 댓글들이 글을 망치고 있는게 아쉬워서 댓글 남겨요

댓글 남기기

이메일은 공개되지 않습니다.

This site uses Akismet to reduce spam. Learn how your comment data is processed.