기록

[GPT가 알려주는] setValue() 와 postValue()의 차이점 본문

잡동사니/GPT가 알려주는

[GPT가 알려주는] setValue() 와 postValue()의 차이점

heylo 2025. 8. 29. 09:47

지금처럼 일반적으로 registerReceiver(context, filter)로 등록한 BroadcastReceiver.onReceive()는 메인 스레드에서 호출되니까, 여기서는 setValue() 써도 안전하고 오히려 좋아요. (게이트/즉시 반영이 필요할 때 유리)

 

 

언제 setValue(), 언제 postValue()?

setValue() (메인 스레드 전용)

  • 지금 이 케이스처럼 onReceive()(메인), 버튼 클릭, LiveData 옵저버 등 UI/메인 스레드에서 호출할 때.
  • 바로 다음 로직에 영향을 줘야 할 때(게이트 변수, 즉시 필터링 등).
  • 예: ACTION_DISCOVERY_STARTED/FINISHED에서 _isScanning을 곧바로 바꿔 즉시 FOUND/NAME_CHANGED를 거르고 싶을 때.
_isBluetoothOn.value = (state == BluetoothAdapter.STATE_ON) // setValue와 동일 (메인에서만)

postValue() (어떤 스레드든 OK)

  • 백그라운드 스레드(IO, Worker, 콜백 스레드 등)에서 값 올릴 때.
  • 즉시성 덜 중요하고, 메인 루퍼에서 조금 있다가 반영돼도 괜찮을 때.
  • 연속 갱신이 많고 합쳐져도 되는 값(마지막 값만 의미 있음)일 때.
    ※ 주의: postValue()는 여러 번 빠르게 호출되면 마지막 값 하나만 전달됩니다(합쳐짐). 카운터처럼 누락되면 곤란한 값에는 부적합.

 

 

예외/주의

  • 만약 registerReceiver(..., ..., ..., handler)처럼 핸들러를 따로 넘겨서 onReceive()가 메인이 아닌 스레드에서 돌게 해놨다면 → setValue()는 크래시, postValue() 써야 합니다.
  • 확실히 하고 싶으면 체크 가능:
val onMain = Looper.myLooper() == Looper.getMainLooper()
if (onMain) _live.value = v else _live.postValue(v)

 

작게 팁 하나:

fun <T> MutableLiveData<T>.safeSet(v: T) {
    if (Looper.myLooper() == Looper.getMainLooper()) value = v else postValue(v)
}

이렇게 쓰면 “어디서 부르든” 안전합니다.