성장기록지

Fragment Manager란? 본문

안드로이드

Fragment Manager란?

pengcon 2024. 12. 30. 19:12

공식문서의 말대로 Jetpack Navigation을 사용한다면  큰 의미가 없겠지만,

프래그먼트를 사용하는 모든 앱은 어느 정도 FragmentManager를 사용하므로

Fragment Manager가 무엇이고 어떻게 작동하는지 파악하는 것이 중요하다 생각하여 학습을 진행한다.

FragmentManager

앱 프래그먼트에서 프래그먼트를 추가, 삭제 또는 교체하고 백 스택에 추가하는 등의 작업을 실행하는 클래스이다.

Activity, Fragment에서 접근가능하다.

 

FragmentActivity 에서 구현하므로, 해당 및 서브클래스에서는getSupportFragmentManager() 메서드를 통해 FragmentManager에 액세스할 수 있다.

 

아래와 같은 Fragment Manager가 있다고 하자.

HostActivity 안에 Host Fragment가 있고, 그 안에 Child Fragement가 있다. (Fragment의 modulality에 의해 가능)

그렇다면 Fragment Manager에 접근할 수 있는 영역이 3개가 생긴것이다.

 

 

 

위의 그림을 그래프로 도식화 해보자면 아래와 같다.

프래그먼트는 하나 이상의 하위 프래그먼트를 호스팅할 수 있다. 프래그먼트 내에서 getChildFragmentManager()를 통해 프래그먼트의 하위 요소를 관리하는 FragmentManager 참조를 가져올 수 있다.

호스트 FragmentManager에 액세스해야 한다면 getParentFragmentManager()를 사용하면 된다.

FragmentManager 활용하기

 

FragmentManager 는 백 스택을 관리한다. 추가, 삭제 등의 작업은 FragmentTransaction 이라는 단일 단위로 함께 커밋된다. addToBackStack() 을 호출하여 트랜잭션을 프래그먼트 백 스택에 추가할 수 있다.

사용자가 뒤로가기 버튼을 누르면 FragmentManager.popBackStack() 을 호출하게 되고 최상위 프래그먼트가 트랜잭션이 스택에서 사라진다.

 

스택에 더 이상 FragmentTransaction 가 없고 개발자가 하위 프래그먼트를 사용하지 않는 경우 뒤로 이벤트가 액티비티까지 간다!

 

트랜잭션에 여러 개의 변경을 추가하고 (add() or remove()) addToBackStack() 을 호출하면 하나의 트랜잭션으로 백 스택에 추가되고 뒤로가기 누르면 한꺼번에 되돌려진다.

 

supportFragmentManager.commit {
   replace<ExampleFragment>(R.id.fragment_container)
   setReorderingAllowed(true)
   addToBackStack("name") // name can be null
}

 

3. 기존 Fragment 찾기

findFragmentById() 또는 findFragmentByTag() 를 사용하여 레이아웃 컨테이너 내의 현재 프래그먼트 참조를 가져온다.

- findFragmentById() 로 찾기

supportFragmentManager.commit {
   replace<ExampleFragment>(R.id.fragment_container)
   setReorderingAllowed(true)
   addToBackStack(null)
}

...

val fragment: ExampleFragment =
        supportFragmentManager.findFragmentById(R.id.fragment_container) as ExampleFragment

- findFragmentByTag() 로 찾기

supportFragmentManager.commit {
   replace<ExampleFragment>(R.id.fragment_container, "tag")
   setReorderingAllowed(true)
   addToBackStack(null)
}

...

val fragment: ExampleFragment =
        supportFragmentManager.findFragmentByTag("tag") as ExampleFragment

 

4. Fragment Defendencies 제공

  기본적으로 FragmentManager 는 프레임워크에서 제공하는 FragmentFactory 를 사용하여 프래그먼트의 새 인스턴스를 만든다. 이 기본 팩토리는 리플렉션을 사용하여 프래그먼트 인자가 없는 기본 생성자를 찾아 호출한다. 즉 기본 팩토리를 사용해서 프래그먼트에 Defendencies 를 제공할 수 없다.

 

종속 항목을 제공하거나 맞춤 생성자를 사용하려면 대신 맞춤FramentFactory 서브 클래스를 만들고FragmentFactory.instantiate 를 재정의 해야한다.

 

class MyFragmentFactory(val repository: DessertsRepository) : FragmentFactory() {
    override fun instantiate(classLoader: ClassLoader, className: String): Fragment =
            when (loadFragmentClass(classLoader, className)) {
                DessertsFragment::class.java -> DessertsFragment(repository)
                else -> super.instantiate(classLoader, className)
            }
}


class MealActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        supportFragmentManager.fragmentFactory = MyFragmentFactory(DessertsRepository.getInstance())
        super.onCreate(savedInstanceState)
    }
}

위 방법 이외에도 companion object 를 사용하여 프래그먼트 내에서 인자를 전달할 수 있다.