MVVM에서 viewModel 이벤트를 수신하는 방법
- LiveData만 있는 이벤트 처리
- EventFlow를 LivieData에 래핑하여 처리
- SingleLiveData로 이벤트 처리
- StateFlow 및 SharedFlow로 이벤트 처리
- SharedFlow, Sealed 클래스로 이벤트 처리
- SharedFlow & Sealed Class & LifeCycle로 이벤트 처리
- EventFlow 및 Sealed 클래스 수명 주기로 이벤트 처리
프로젝트 설정
프로젝트 설정 방법을 간략하게 설명하겠습니다.
다음과 같이 사용자 인터페이스를 구성합니다.

다음 조치를 취했습니다.
- 각 버튼을 클릭합니다.
- liveData 또는 Flow 변수에 데이터를 삽입합니다.
- 변수 2번에서 watch를 실행하고 watcher가 되면 빈 액티비티를 엽니다.
- 다시 이전 활동으로 돌아가 변수 2번에 저장된 값을 확인합니다.
LiveData만으로 데이터 처리
ViewModel 구성
class LiveDataViewModel: ViewModel() {
private val _someData = MutableLiveData<Int>()
val someData: LiveData<Int> = _someData
fun setData() {
if (_someData.value == null) {
_someData.value = 0
} else {
_someData.value = _someData.value!! + 1
}
}
}
테스트를 위한 활동 구성
class FirstActivity : AppCompatActivity() {
private lateinit var binding: ActivityFirstBinding
private val liveDataViewModel: LiveDataViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityFirstBinding.inflate(layoutInflater)
setContentView(binding.root)
lifecycleScope.launch {
liveDataViewModel.someData.observe(this@FirstActivity) {
Timber.d("data observed: $it")
startActivity(Intent(this@FirstActivity, SecondActivity::class.java))
}
}
binding.liveDataButton.setOnClickListener {
liveDataViewModel.setData()
}
}
override fun onResume() {
super.onResume()
Timber.d("liveDataViewModel Data: ${liveDataViewModel.someData.value}")
}
}
검사 결과

직장에서 돌아왔다 기존 데이터가 보존된다는 것 당신은 확인할 수 있습니다
여기에 데이터를 남기지 않으려면 EventWrapper를 사용하십시오.
LiveData에 EventWrapper 적용
EventWrapper 클래스를 정의하여 화면으로 돌아올 때 다시한번 관찰불가
값을 초기화하는 방법 구글이 한때 사용한 방법이 있다.
여기서 언급하는 EventWrapper 클래스는 다음과 같이 정의할 수 있습니다.
/**
* Used as a wrapper for data that is exposed via a LiveData that represents an event.
*/
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set // Allow external read but not write
/**
* Returns the content and prevents its use again.
*/
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) {
null
} else {
hasBeenHandled = true
content
}
}
/**
* Returns the content, even if it's already been handled.
*/
fun peekContent(): T = content
}
위의 EventWrapper를 사용하기 위한 ViewModel은 다음과 같이 정의됩니다.
class EventLiveDataViewModel: ViewModel() {
// LiveData에 EventWrapper를 적용한다.
private val _someData = MutableLiveData<Event<Int>>()
val someData: LiveData<Event<Int>> = _someData
fun setData() {
if (_someData.value?.getContentIfNotHandled() == null) {
_someData.value = Event(0)
} else {
_someData.value = Event(_someData.value?.getContentIfNotHandled() as Int + 1)
}
}
}
그리고 테스트할 활동은 다음과 같이 정의됩니다. (이제부터는 생략)
class FirstActivity : AppCompatActivity() {
private lateinit var binding: ActivityFirstBinding
private val liveDataViewModel: LiveDataViewModel by viewModels()
private val eventLiveDataViewModel: EventLiveDataViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityFirstBinding.inflate(layoutInflater)
setContentView(binding.root)
lifecycleScope.launch {
liveDataViewModel.someData.observe(this@FirstActivity) {
Timber.d("data observed: $it")
startActivity(Intent(this@FirstActivity, SecondActivity::class.java))
}
}
lifecycleScope.launch{
eventLiveDataViewModel.someData.observe(this@FirstActivity) {
Timber.d("data observed: ${it.getContentIfNotHandled()}")
startActivity(Intent(this@FirstActivity, SecondActivity::class.java))
}
}
binding.liveDataButton.setOnClickListener {
liveDataViewModel.setData()
}
binding.liveEventDataButton.setOnClickListener {
eventLiveDataViewModel.setData()
}
}
override fun onResume() {
super.onResume()
Timber.d("liveDataViewModel Data: ${liveDataViewModel.someData.value}")
Timber.d("eventLiveDataViewModel Data: ${eventLiveDataViewModel.someData.value?.getContentIfNotHandled()}")
}
}
그리고 eventLiveDataViewModel 버튼을 클릭하면 다음과 같은 로그가 출력됩니다.

화면이 처음 열리면 null을 반환합니다.
관찰 후 다른 활동으로 전환했다가 복귀한 후에도 값이 지속됩니다. 다시 제로입니다.
이것은 EventWrapper 때문입니다. 한 번 시청 null을 반환하기 때문입니다.
getContentIfNotHandled ~ 아니다 peekContent 이를 사용하여 값을 가져오면 일반 LiveData를 사용하는 것처럼 사용할 수 있습니다.
MVVM에서 viewModel 이벤트를 수신하는 방법 요약
- LiveData만 있는 이벤트 처리
- EventFlow를 LivieData에 래핑하여 처리
다음 포스트에서는 SingleLiveData와 SharedFlow에 대해 살펴보겠습니다.