프로젝트를 MVVM 형태로 구현하다 보면 ViewModel 에서 LiveData 를 쓰는 경우가 많습니다.
보통 private 로 선언된 MutableLiveData 의 value 를 변경하고
public 으로 선언된 LiveData 의 값을 관측하는 식으로 사용합니다.
그런데 이 과정에서 Coroutine 을 사용하다 보면 아래 상황에서 오류가 발생합니다.
DB 작업을 하는 백그라운드 스레드에서 setValue 를 호출
그리고 이러한 오류를 마주치게 되죠
java.lang.IllegalStateException: Cannot invoke setValue on a background thread
setValue 메서드는 백그라운드에서 호출할 수 없다고 합니다.
그래서 백그라운드에서는? postValue 를 사용해야합니다.
하지만 postValue 는 setValue 와는 다르게 값을 '즉시 적용' 하는 개념이 아니라
아래와 같이 백그라운드에서 핸들러를 통해 setValue 를 post 해주는 형태입니다.
new Handler(Looper.mainLooper()).post(() -> setValue())
그렇기 때문에 postValue 이후에 바로 LiveData 의 값을 찍어보면 적용이 되지 않습니다
아래의 코드처럼 말이죠
mData.postValue(repository.getAll())
println(data.value)
// 이 코드는 null 을 반환할 수 있습니다
그렇기 때문에 LiveData 에 즉각적으로 변화를 주고자 한다면 UI 스레드에서 setValue 를 호출하는 것이 좋습니다.. 만
상황적인 차이가 있고, DB 에서 가져오는 데이터처럼 양이 굉장히 많다던지 하여
UI 스레드를 장시간 차단할 우려가 있는 경우에는 백그라운드에서 postValue 를 사용하여 비동기로 데이터를 세팅한 뒤
UI 스레드에서는 작업을 최소화해주시는게 좋습니다.
(빨리 빨리 반영되야한다고 무작정 UI 스레드로 당겨와서 setValue 했다가 ANR(Android Not Respond: 응답없음) 이 발생할 수도 있습니다)
어짜피 LiveData 는 Observable 한 객체기 때문에 데이터가 들어오는걸 관측해서 UI 스레드 작업을 하는데 지장이 전혀 없기도 하고요..!
'Android > Kotlin' 카테고리의 다른 글
Android 에서 Google 소셜 로그인을 구현해보자 (1) | 2024.06.11 |
---|---|
Jetpack Compose 에서 기존 View 를 사용하고자 한다면! (0) | 2024.05.27 |
Android SpeechRecognizer 를 이용해 음성 인식 구현하기 (1) | 2024.02.29 |
Android 배워보자 Compose! -(5) Scaffold / BottomNavigation (1) | 2024.02.14 |
Jetpack Compose 에서 Dialog 구현하기 (1) | 2024.02.07 |