프로그래밍/안드로이드, 코틀린
옵저버 패턴으로 직접 LiveData 만들어보기
toonraon
2023. 7. 6. 10:10
Android Jetpack에 포함되어있는 유명한 라이브러리 중 하나가 LiveData입니다.
값의 변화를
liveData.observe(this, Observer {
// ...
})
이런 식으로 관찰해서 사용할 수 있기 때문에 많이 사용됩니다.
그리고 이 LivaData가 디자인 패턴 중에 옵저버 패턴을 사용하는 대표적인 예시 중 하나이기 때문에
옵저버 패턴을 공부할 겸 평소에 유용하게 쓰던 LiveData를 직접 구현해보겠습니다.
class SimpleLiveData<T> {
private var data: T? = null
private val observers = mutableListOf<(T?) -> Unit>()
fun observe(observer: (T?) -> Unit) {
observers.add(observer)
observer(data)
}
fun setValue(newValue: T) {
data = newValue
observers.forEach { it(data) }
}
fun getValue(): T? {
return data
}
}
observe() 함수를 통해서 observer를 인자로 넘깁니다.
observer는 (T?) -> Unit 이므로 아무 인자 1개(혹은 null)를 받은 후, Unit을 return하는(=딱히 return하는 게 없는) 람다식이 넘어옵니다.
이 인자로 넘어온 람다 함수를 observers라는 mutableList에 추가합니다.
그리고 그 함수를 바로 실행시킵니다.
이때 이 함수의 인자로는 현재 data를 넘겨줍니다.
이 observer(data) 가 있기 때문에 처음에 observe() 함수로 옵저버를 붙이자마자 현재 데이터에 대해 값을 뱉어줄 수 있습니다.
만약에 얘가 없고 observe() 함수 안에 observers.add(observer) 이거 한 줄만 있었다면
처음에 옵저버를 붙일 때 현재 값에 대해서 return이 안 될 겁니다.
그리고 setValue를 할 때마다 data에 해당 값을 저장하고, 모든 observer들에게 그 값에 대해서 인자로 넘겨서 람다함수를 실행하게 만듭니다.
fun main() {
val liveData = SimpleLiveData<Int>()
liveData.observe { value ->
println("Observer1: $value")
}
liveData.setValue(5)
liveData.observe { value ->
println("Observer2: $value")
}
liveData.setValue(10)
// Observer1: null
// Observer1: 5
// Observer2: 5
// Observer1: 10
// Observer2: 10
}
이와 같이 사용할 수 있습니다.