Android

[안드로이드] Fragment(프래그먼트) 와 Fragment Manager

베르_최성훈 2023. 5. 8. 08:32

Fragment 란?

테블릿처럼 큰 화면에서 기존엔 Activity 두개를 띄우거나 했지만 서로 다른 생명주기를 가져서 관리가 힘들었다..!! 

그래서, 동일한 액티비티 생명주기를 공유하지만 화면을 서로 다르게 사용하기 위해 Fragment 가 탄생했다.

 

Fragment 는 FragmentActivity 내의 어떤 동작 또는 사용자 인터페이스 일부를 나타낸다. 

 

Activity 와 결합하여 창이 여러개인 UI 를 빌드할 수 있으며 하나의 Fragment 여러 Activity 에서  재사용할 수 있다.

자체적인 생명 주기를 가지며 자체 입력 이벤트를 수신하고 Activity 실행 중에 추가 및 삭제가 가능하다.

 

 

Fragment 는 항상 액티비티 내에서 호스팅되어야 하며 액티비티의 생명 주기에 직접적인 영향을 받는다!

  • 액티비티 가 Paused -> 모든 프래그먼트도 Paused
  • 액티비티가 Destoryed -> 모든 프래그먼트도 Destroyed

 

그러나! 액티비티가 실행 중인 동안 프래그먼트를 추가, 제거하는 등 개별적 조작이 가능하다. 

이러한 조작을 프래그먼트 트랜잭션이라고 한다. 

 

트랜잭션을 수행할 때 액티비티가 관리하는 백스택에도 추가할 수 있다.

백스택을 사용하면 사용자가 트랜잭션 을 거꾸로 돌리는 것도 가능하다.

 

Fragment 를 액티비티 레이아웃에 추가하면 해당 프래그먼트는 액티비티 View 계층 내에서 ViewGroup 에 들어가고 자체적인 뷰 레이아웃을 정의한다. ViewGroup 에 추가하거나 액티비티 레이아웃 파일에서 선언하면 액티비티 레이아웃에 삽입할 수 있다.

 

장점

  • 액티비티에 종속적인 생명주기를 따르므로 부분 화면 관리에 용이함
  • 시스템 개입이 없으므로 액티비티 사용시 보다 화면 전환의 부담이 적음
  • 재활용 가능

Fragment Manager

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

 

* Jetpack Navigation 라이브러리를 사용하는 경우 FragmentManager 와 상호작용은 거의 필요하지 않음.

그러나 개발자가 알고 쓰는 것이 중요!

 

1. FragmentManager  에 엑세스

 

  • Activity 에서 액세스
    모든 FragmentActivity 및 그 서브클래스(ex: AppCompatActivity) 는 getSupportFragmentManager() 로 액세스 가능

  • 프래그먼트는 하위 프래그먼트를 하나 이상 호스팅할 수 있다.
    getChildFragmentManager() 를 통해 프래그먼트 하위 요소를 관리하는 FragmentManager 를 참조할 수 있다.
    호스트 FragmentManager 에 액세스 하려면 getParentFragmentManager() 사용

FragmentManager 참조가 있으면 이를 사용하여 사용자에게 표시되는 프래그먼트를 조작할 수 있다.

 

2. 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)
    }
}

 

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

 

- 출처

https://developer.android.com/guide/fragments/fragmentmanager

 

프래그먼트 관리자  |  Android 개발자  |  Android Developers

프래그먼트 관리자 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 참고: Navigation 라이브러리를 사용하여 앱의 탐색을 관리하는 것이 좋습니다. 프레임워크

developer.android.com