안녕하세요 점냥입니다 :)
Fragment에서 클릭 이벤트 또는 특정 데이터를 외부로 전달하고자 하는 경우가 많아요. 이를 구현하기 위해 여러 가지 방법이 존재하는데요. 이번 포스팅에서는 Callback을 이용하여 데이터를 전달하는 방법을 소개해보려고 합니다.
잘못된 부분이나 더 좋은 방안이 있다면 댓글로 남겨주세요!
Callback을 이용한 데이터 전달
Callback 패턴이 가장 쉽게 구현할 수 있는 방법인데요. Callback이란 다른 함수의 인자로써 넘겨진 후 특정 이벤트에 의해 호출되는 함수를 의미합니다. Android에서는 Listener라고도 부르며 주로 Interface를 구현한 객체를 넘기거나 최근에는 Lambda를 이용하는 모습이 자주 보여요.
setter 함수로 콜백 전달하기
class SampleDialog: DialogFragment() {
private var listener: (() -> Unit)? = null
fun setListener(listener: () -> Unit) {
this.listener = listener
}
...
}
가장 원초적인 방법으로 private 접근 지정자 없이 열어두거나 setter 함수를 열어두는 방법이에요. 외부에 의존성이 없는 방식이기 때문에 선호했던 방식이지만 문제점이 하나 있었습니다.
Bundle로 복원 불가능
Android 앱은 시스템으로 인해 재생성이 될 수 있어요. Fragment도 피해 갈 수 없습니다. 이때 기본적으로 가지고 있던 데이터들이 날아가기 때문에 사용자의 경험, 중요한 데이터의 손실을 막기 위해 데이터를 저장/복원해주는 작업이 필요합니다.
Fragment의 Callback 함수는 자체적으로 생성하는 것이 아닌 외부에서 주입해주는 데이터이기 때문에 저장/복원 대상에 포함되어야 하는데요. 문제는 Lambda를 Bundle에 넣는 것이 불가능한 상황에서 재생성될 때 Setter 함수를 다시 호출해줄 보장이 없기 때문에 콜백 객체를 복원하기가 어렵습니다.
Fragment 참조하고 있는 부모 객체 자체를 리스너 구현 객체로 만들기
class SampleFragment: DialogFragment() {
override fun onAttach(context: Context) {
super.onAttach(context)
listener = requireActivity() as? SampleClickListener
}
}
interface SampleClickListener {
fun onClick()
}
이 방법은 Fragment의 참조를 가진 Activity 혹은 parentFragment 자체에서 리스너를 구현하는 방식이에요. Lambda 대신 interface를 이용한 방법으로 setter와 다르게 재 성성될 때도 onAttach 콜백 함수에서 리스너를 재설정하는 것이 가능합니다.
하지만 참조 하고있는 부모가 interface를 구현했는지 알기 어려워요. 의존성이 생기는 방법이기 때문이에요. 따라서 여러 명이 협업하는 프로젝트일 경우 문제가 생길 수도 있습니다.
참고
- kotlin - How to save and restore lambdas in Android? - Stack Overflow
'Android > Common' 카테고리의 다른 글
[Android] Radius 올바르게 적용하기 (0) | 2023.05.24 |
---|---|
[Android] Fragment에서 데이터 외부로 전달시키는 방법 - ActivityViewModel (0) | 2022.12.06 |
[Android] Very Long Vector Path 해결 (0) | 2022.11.18 |
[Android] 디버그 앱, 출시 앱 분리하기 (4) | 2022.11.12 |
[Android] Flow 흐름을 turbine으로 쉽게 테스트 코드 작성해보기 (2) | 2022.10.27 |