FragmentManager와 ChildFragmentManager

허니컴(Honeycomb)부터 액티비티나 프레그먼트 안에 프레그먼트를 추가할 수 있다. 이 프레그먼트 객체를 관리하는 것이 FragmentManager다. 프레그먼트 전반에 대한 소개는 공식문서를 참고하고, 여기서는 종종 헷갈려하는 FragmentManager와 일명 ChildFragmentManager의 차이점에 대해서만 설명한다.

먼저 ChildFragmentManager라는 용어부터 짚고 넘어가자. ChildFragmentManager라는 클래스는 따로 없다.  대신, Activity.getFragmentManager()나 Fragment.getFragmentManager()에서 반환하면 FragmentManager(이하 FM), Fragment.getChildFragmentManager() 메소드에서 반환되는 FragmentManager 객체를 ChildFragmentManager(이하 CFM)라고 보통 부른다.

FM과 CFM 모두 FragmentManager 클래스의 객체이니, 동작은 유사하다. 하지만, 실제 사용 시에는 헷갈린다.

  • FM은 액티비티, 액티비티 속 프레그먼트(이하 자식 프레그먼트) 그리고 프레그먼트 속 프레그먼트(이하 손자 프레그먼트)가 모두 사용할 수 있다.
  • CFM은 프레그먼트(자식)와 프레그먼트 속 프레그먼트(손자)들만 사용할 있다.
  • FM에서 관리되는 손자 프레그먼트라면, getFragmentManager()는 액티비티의 getFragmentManager()와 동일한 객체를 반환한다.
  • CFM에서 관리되는 손자 프레그먼트라면, getFragmentManager()는 부모(액티비티의 자식) 프레그먼트의 getChildFragmentManager()와 동일한 객체를 반환한다.

위와 같이 FM과 CFM은 다른 객체이므로 FragmentManager.findFragmentBy…() 메소드의 결과도 다르다. FM이 관리하는 프레그먼트는 FM에서, CFM에서 관리하는 프레그먼트는 CFM에서 찾아야할 것이다.

번거롭게 왜 두개를 유지하는 것일까? API 11에는 getFragmentManager()만 있었다. 그 후, API 17부터 getChildFragmentManager()가 추가된다. 두 개로 유지하는 것의 장점은 remove() 메소드를 통해 프레그먼트를 제거할 때 더 잘 알 수 있다. (여기서 제거란 화면에서 보이는지 여부가 아닌, …onDestroy(), onDetach()로 이어지는 프레그먼트 객체 소멸을 말한다.)

액티비티-자식프레그먼트-손자 프레그먼트의 계층구조를 가진 액티비티가 있다. 여기서 자식 프레그먼트를 제거한다고 해보자. 손자 프레그먼트가 FM에서 관리된다면 자식 프레그먼트만 제거된다.  반면, 자식 프레그먼트의 CFM을 통해 손자 프레그먼트가 관리된다면, 손자프레그먼트가 먼저 제거된 후 자식 프레그먼트가 제거된다. 이는 프레그먼트의 계층구조로 인해 오는 관리의 어려움을 쉽게 만들 수 있다.

마지막으로, 위와 같은 구조가 startActivityForResult()의 결과에도 영향을 미칠까? 그렇지 않다. 어떤 액티비티나 프레그먼트에서 호출하든, startActivityForResult()의 결과를 onActivityResult()를 통해 받을 수 있다.  FM이나 CFM 어디에서 관리하든 상관 없이 startActivityResult()를 호출했던 프레그먼트로 결과가 반환된다. Fragment.onActivityResult()의 동작도 헷갈리는 부분이 있다면 이 글을 참고하자.

그 밖에

  • support library의 FragmentActivity를 상속받아 만든 액티비티의 경우는 getSupportFragmentManager()를 통해 FragmentManager 객체를 얻는다.
  • Activity 클래스의 getFragmentManager()는 P OS부터 deprecated 된다.

참고

“FragmentManager와 ChildFragmentManager”에 대한 4개의 생각

  1. 잘 읽었습니다. 자연스레 FCM으로 쓰신 부분들이 많네요!ㅎㅎ FCM -> CFM 아닌가요?

  2. 제가 이해한게 맞는지 모르겠네요
    FM CFM
    Activity 자식 Frag
    자식 Frag 손자 Frag
    손자 frag
    구조가 이렇게되고 만약 자식 접근시
    FM: getFragmentManager를 2번 호출 해야하고
    CFM:etFragmentManager를 1번 호출
    만약 손자 접근시
    FM: 3번
    CFM:2번 이 맞나요 ?

    1. 어쩌면 fm과 cfm을 계층구조로 이해하신게 아닌가 싶습니다. fm은 액티비티에서 쓰는 것과 같은 인스턴스를 cfm은 프레그먼트 마다 새 인스턴스를 반환하는 특징이 있을 뿐, 계층 구조는 아니라서 자손을 찾기위해 반복적으로 호출하실 필요는 없는데요. 아마도 제 글의 설명이 모자랐나봐요.

yongbeomkwak에게 댓글 남기기 댓글 취소

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

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.