본문 바로가기

TIL

[TIL] Fragment ResultListener로 데이터 옮기기

[오늘 배운 내용]

-1- FragmentResultListener

  • FragmentResultListener??
    • Android Jetpack의 Fragment API에서 제공하는 인터페이스이다. 해당 인터페이스를 통해 Fragment 간에 데이터를 전달하고 결과를 수신할 수 있다.
    • Fragment 와 Activity와 Fragment 간에 데이터를 전달하는데, RecyclerView를 표시하고 있는 Fragment 에서 선택한 항목의 세부정보를 표시하는 다른 Fragment로 데이터를 전달하는 것과 같이 일회성 값을 전달하는 상황에 사용하기에 유용하다.
  • Bundle을 통한 데이터 전달방식과 FragmentResultListener의 차이점
    • FragmentResultListener는 Fragment 간에 데이터를 비동기적으로 전달하기 위한 인터페이스이다. 때문에 보내는 측과 수신측의 실행 시점이 다르더라도 데이터가 정확하게 전달이 된다. 이로인해 보내는 측과 수신 측 간의 결합도를 낮추고 모듈성을 향상시킬 수 있다.
    • Bundle방식은 데이터를 직렬화하여 전달하는 일반적인 방법이다. 이는 보내는 측과 수신 측의 실행 시점이 동일해야하며, 번들을 직접 조작해야 한다. 이 방식은 동기적인 상황에서 사용하기에는 제약이 있을 수 있다.

 

FragmentResultListener 적용방법

  • build.gradle(module) 에 추가
dependencies {
    ...
    implementation ("androidx.fragment:fragment-ktx:1.6.1")
    
}

 

  • FragmentB에서 setFragmentResult("requestKey",bundle) 으로 map형태인 bundle을 FragmentManager로 넘겨주면, 해당 Data를 받기를 원하는 Fragment인 FragmentA에서 setFragmentResultListener("requestKey")로 FragmentManager 로부터 requestKey의 bundle을 받아올 수 있고 받아온 리스트 키에 해당하는 번들을 requestKey, bundle -> bundle.getXXX(bundleKey) 으로 FragmentB에서 보낸 bundleKey에 해당하는 data를 받게된다. 작동 코드를 보면서 설명을 봐보자.

 

Android Develpopers에서 제공하는 FragmentManager를 사용하여 동일한 선상의 FragmentB에서 FragmentA로 데이터를 전송하는 것을 설명하는 그림이다.

 

FragmentResultListener 사용방법

예시에서 FragmentA 라고 하면 Data를 받는 Fragment고, FragmentB 는 Data를 넘겨주는 Fragment로 가정.

  •  FragmentB 에서 button 클릭 시 data를 넘기는 예시. setFragmentResult("requestKey") 의 requestKey는 FragmentA에서 값을 찾아올 때 필요한 키값으로 string의 형태내에서 내가 원하는대로 key이름을 설정해서 사용할 수 있다.
  • bundle은 bundleKey와 넘길 data의 쌍으로 map형태로 이루어서 지정해둔다.
button.setOnClickListener {
    val result = ??? // ??? == 이동시킬 Data
    setFragmentResult("requestKey", bundleOf("bundleKey" to result))
}

 

  • FragmentB에서 데이터를 FragmentManager로 올리는 코드를 작성한 뒤에, FragmentA로 이동해서 setFragmentResultListener로 FragmentB에서 지정한key와 동일한requestKey와 bundle.getXXX(bundleKey)를 이용해서 데이터를 받아오면 된다. 이때 XXX는 FragmentB에서 보낸 data의 형태이다.
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Gradle(module) 에 fragment dependencies 추가해주어야 함.
    setFragmentResultListener("requestKey") { requestKey, bundle ->
        // We use a String here, but any type that can be put in a Bundle is supported.
        val result = bundle.getXXX("bundleKey")
        // Do something with the result.
    }
}

 

 

부모Fragment와 자식Fragment간의 데이터 이동

  • 부모Fragment와 자식Fragment간의 데이터 이동에서 자식 Fragment의 값을 부모가 받는 경우 childFragmentManager를 통해 결과를 받아온다. 

 

  • 하위 Fragment는 FragmentManager에 data를 설정한다.
button.setOnClickListener {
    val result = "result"
    setFragmentResult("requestKey", bundleOf("bundleKey" to result))
}

 

 

  • 하위 Fragment의 Data를 상위 Acitivty,Fragment 등의 컴포넌트에서 전달받으려면 setFragmentResultListener()를 호출할 때 getParentFragmentManager() 대신 상위 프래그먼트의 getChildFragmentManger()를 사용한다.
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Set the listener on the child fragmentManager.
    childFragmentManager.setFragmentResultListener("requestKey") { key, bundle ->
        val result = bundle.getString("bundleKey")
        // 받아온 data 처리
    }
}

 

 

 

 

 

 

 

 


 

[오류,에러 등등]

1. 새로 배운 기능들 복습 위주로 진행하느라 별다른 오류는 없었다.

 

2.

 

3.

 


[느낀 점]

1. 기능을 적용했다고 해서 코드를 다 이해한 게 아닌 것 같다. 정리하면서 다시 한번 복습하는 습관을 가져야겠다.

 

2. 어렵다.

 

3. 시간이 너무 빠르다..

 

 


[Reference]

 

// FragmentResultListener

https://moon-i.tistory.com/entry/Fragment-Result-API

https://moon-i.tistory.com/entry/Fragment-Result-API

https://developer.android.com/guide/fragments/communicate?hl=ko