Fragment간 데이터 전달 방법에 대해서..
Fragment간 데이터 전달 방법에 대해서..
안드로이드를 개발하다 보면 서로 다른 Activity와 Fragment간 데이터를 주고 받아야하는 경우가 있습니다. 저는 대표적으로 상태 값이나 처리에 필요한 데이터들이 많았습니다. 기존에는 Bundle을 활용하여 데이터 값을 주고 받았습니다. Stirng 타입의 데이터를 하나 보낸다면 크게 문제는 없었지만, 2개 이상부터 이름다른 Key 값과 중복되는 코드가 증가되고 가독성이 떨어지는 문제가 있었습니다. 그래서 이를 개선하기 위해 다양한 시도를 해보았습니다.
Fragment Result 테스트해보기
사진과 같이 Fragment Manager에서 처리할 수 있어서 간단하다 생각하였습니다. 특히나 setFragmentResultListener 통해 다른 Fragment에서도 참조할 수 있다는 점에서 매우 좋아 보였으나 Fragment에서 한정으로 이루어지기 때문에 Activity가 다르다면 데이터를 주고 받을 수 없었습니다. 그래서 이 방법은 제가 이용하려고 하는 목적으로는 맞지 않다 판단하였습니다.
ViewModel 공유로 테스트 해보기
하나의 Activity에서 container로 여러 Fragment를 사용할 경우 사용할 수 있습니다. Activity의 ViewModel 공유하는 여러 Fragment들은 Activity의 메모리를 공유할 수 있고 AAC의 ViewModel은 Activity의 lifecycle보다 오래 살아있는 것이 보장되기 때문에 안전하게 공통의 Activity의 ViewModel을 사용하여 데이터 전달이 가능하여 테스트를 해보았습니다.
Fragment간 데이터를 주고 받는데에는 문제가 없었습니다. 그러나 아직 실력이 부족해서 그런지 한가지의 의문점이 들었습니다. Activity의 ViewModel도 존재하고 각 Fragment의 ViewModel도 존재하고 그렇다면 꾸준히 데이터를 Fragment계속 공유해야 한다면 좋은 방법일 수 있지만 1회성과 지속성인 데이터가 아니기 때문에 필요하지 않다 판단하였습니다.
결국엔…
이외에도 Jetpack의 Navigation을 활용하여 데이터를 주고 받을 수 있지만, 저는 Home 화면에서만 사용하고 다른 화면에서는 안쓰고 있어서 이 방법또한 현재 상황에서는 맞지 않다 생각하였습니다. 그렇다면 기존에 코드를 개선을 해보자 하였습니다.
inline fun <reified T : Activity> Context.buildIntent(
vararg argument: Pair<String, Any?>
): Intent = Intent(this, T::class.java).apply {
putExtras(bundleOf(*argument))
}
...
Adapter { text ->
parentFragmentManager.transformFragment<SearchFragment>(
R.id.container,
"search" to text.encodeToString()
)
}
...
Kotlin의 Extender 기능을 활용하여 Context에서 buildIntent이란 추가 확장 함수를 만들고, Fragment나 Activity에 보내려고하는 데이터를 가변인자로 받아 여러 인자를 처리할 수 있도록 하였습니다. 이렇게 될 경우 호출 될때에 인자 값만 넣어주기만 하면 문제가 없어지기 때문입니다. 기존 반복되던 코드들은 많이 줄일 수 있었고 코드 가독성을 개선할 수 있었습니다. 추가적으로 객체를 직렬화를 통해 Fragment간 객체도 주고 받을 수 있도록 추가로 개선하였습니다.