Programming/Android

[Android] LiveData 에서 쓰이는 setValue() & postValue()

Aosta 2022. 12. 1. 14:17

예전에 규모가 커진 앱의 기능 일부를 떼어내서 신규 앱을 런칭해야 하는 일이 있었습니다.

그때 마침 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() 를 하게되면 값을 불러오지 못한다는 경우였습니다.