몰?.루();

옵저버 패턴으로 직접 LiveData 만들어보기 본문

프로그래밍/안드로이드, 코틀린

옵저버 패턴으로 직접 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
}

이와 같이 사용할 수 있습니다.

Comments