본문 바로가기

Android

Fragment Result API

* 공식문서 번역 

 

Fragment 간 데이터 전달을 위해 viewModel을 사용하기도 하고, interface를 사용하기도 하고 여러 방법을 사용하는데 Activity Result 같이 Fragment Result도 있다고 한다.. 언제생겼지..!

어떤경우 사용하나

  • 일회성 데이터를 fragment간, 혹은 fragment 와 host activity간 전달하고 싶을 때 사용한다.

Fragment 1.3.0-alpha04 이후부터 FragmentManager는 FragmentResultOwner를 구현한다. (상속받아)

이것은 Fragment Manager가 fragment 결과의 central store로 동작할수 있다는것을 의미한다.

이제 component간 직접 참조 하지 않고, fragment의 result를 설정하고, 결과를 수신 및 수신 대기해서 서로 데이터를 전달 할 수 있게됐다~

1. Fragment간 result 전달 하기

  • Fragment B에서 Fragment A에게 데이터를 전달하기 하기 예제
  • 먼저 Fragment A에 result Listener를 설정 - result를 받을 fragment
  • Fragment A의 FragmentManager에서 setFragmentResultListener() 를 호출
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Use the Kotlin extension in the fragment-ktx artifact
    setFragmentResultListener("requestKey") { requestKey, bundle ->
        // We use a String here, but any type that can be put in a Bundle is supported
        val result = bundle.getString("bundleKey")
        // Do something with the result
    }
}

 

  • Fragment B에서는 result 를 생성한다.
  • setFragmentResult() api를 이용해서 같은 FragmentManager에 같은 requestKey로 result를 set 한다
button.setOnClickListener {
    val result = "result"
    // Use the Kotlin extension in the fragment-ktx artifact
    setFragmentResult("requestKey", bundleOf("bundleKey" to result))
}
  • Fragment A 상태가 started될때 result를 받고, listener callback이 실행된다.
  • 하나의 키에는 하나의 listener 결과만 있을 수 있다. 동일한 키에 setFragmentResult를 두번이상 호출하는 경우 시스템은 대기중인 결과를 업데이트된 결과로 변경한다. 리스너가 started상태가 아닌경우 동일
  • 결과를 수신할 listener가 없이 setFragmentResult만 설정되어 결과가 있는경우, 동일한 키로 리스너가 설정될때까지 FragmnetManager에 결과가 저장된다.
  • listener가 결과를 받고 onFragmentResult를 실행하면 결과는 삭제된다.
    • BackStack에 있는 Fragment는 상태가 STARTED로 변경되기 전까지 결과를 받지 않는다
    • 결과를 기다리는 fragment가 STARTED 상태이고, 결과가 설정되면 listener의 callback이 바로 실행된다.

2. Parent, Child Fragment간 result 전달하기

  • 부모자식간의 결과 데이터를 주고받기 위해서는 setFragmentResultListener()가 호출될때 getChildFragmentManager를 사용해야한다 (getParentFragmentManager대신)

  • ChildFragmentManager에 listener등록
  • 자식은 FragmentManager에 결과 설정, 부모 fragment가 started상태가 되면 상위 fragment에서 결과를 수신

부모

// 부모 fragment
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // We set the listener on the child fragmentManager
    childFragmentManager.setFragmentResultListener("requestKey") { key, bundle ->
        val result = bundle.getString("bundleKey")
        // Do something with the result
    }
}

자식

button.setOnClickListener {
    val result = "result"
    // Use the Kotlin extension in the fragment-ktx artifact
    setFragmentResult("requestKey", bundleOf("bundleKey" to result))
}

3. Host Activity에서 결과 받기

Host Activity에서 fragment result를 받으려면 getSupportFragmentManager()를 사용해서 fragment manager에 listener 설정

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportFragmentManager
                .setFragmentResultListener("requestKey", this) { requestKey, bundle ->
            val result = bundle.getString("bundleKey")
        }
    }
}

끝~