[Android] LiveData 에서 쓰이는 setValue() & postValue()
예전에 규모가 커진 앱의 기능 일부를 떼어내서 신규 앱을 런칭해야 하는 일이 있었습니다.
그때 마침 MVVM 패턴에 관심이 많았던 시기라 MVVM을 기반으로 한 프로젝트를 진행했습니다.
그러면서 처음으로 LiveData 에 대해서 공부했었는데, 당시에는 setValue() 와 postValue() 를 각각 써보면서,
에러가 나거나 성능에 큰 차이가 없다고 느껴서 그냥 넘어갔던 적이 있었습니다.
Unit test 를 공부하다가 ViewModel 을 테스트 하는 상황이 생겨, LiveData 를 다시 만나게 되고 테스트 하는 방법을 찾던 중 좋은 글을 발견해서 글을 남기려고 합니다.
https://jeroenmols.com/blog/2019/01/17/livedatajunit5/
추후에 LiveData 를 테스트 하는 것은 따로 작성할 생각이고, 여기서 LiveData 자체에 대한 것은 다루지 않으려고 합니다.
setValue()
@MainThread
protected void setValue(T value)
// https://developer.android.com/reference/androidx/lifecycle/LiveData#setValue(T)
setValue() 는 말그대로 LiveData 에 값을 저장(Set) 하는 것입니다.
공식 문서를 보면 @MainThread 어노테이션이 달려있는 것처럼, 반드시 메인 스레드에서 호출되어야 하는 메소드입니다. 만약 백그라운드 Thread 에서 값을 변경하고 싶을 땐 postValue() 를 사용해야 합니다.
postValue()
postValue() 도 setValue() 와 같이 LivaData 에 값을 저장하는 동일한 기능을 합니다.
차이점은 postValue() 는 백그라운드 스레드 에서 값을 변경 후, 메인 스레드에 값을 전달한다는 것입니다.
이 차이점으로 인해 아래와 같은 상황이 발생합니다.
liveData.postValue("a")
liveData.setValue("b")
예시를 보면 "a" 값을 먼저 postValue 하고 그 직후에 "b" 값을 setValue 합니다.
위 코드 직후 liveData 에는 값이 뭐가 들어있을까요?
나중에 실행된 코드인 "b" 가 아닌 "a" 가 저장되어 있습니다.
이유는 setValue() 는 메인스레드에서 직접 값을 변경했지만 postValue() 는 백그라운드 스레드에서 값을 변경 후 다시 메인스레드로 변경된 것(Task) 를 주기 때문에 "a"가 저장되게 됩니다.
이런 이유로 실제 프로젝트에 적용할 때 겪었던 일이 있었습니다.
바로 postValue() 를 하자마자 바로 getValue() 를 하게되면 값을 불러오지 못한다는 경우였습니다.