Android/Kotlin
안드로이드 MVVM 이벤트 처리
easy-1
2021. 10. 18. 11:14
<개요>
ViewModel, LiveData, DataBinding 을 사용하여 이벤트를 처리하는 방법
<적용 방법>
1. Event Class 정의
- 하나의 이벤트에 대해 한번만 처리됨
open class Event<out T>(private val content: T) {
var hasBeenHandled = false
private set
fun getContentIfNotHandled(): T? {
return if (hasBeenHandled) { // 이벤트가 이미 처리 되었다면
null // null 을 반환하고
} else { // 그렇지 않으면
hasBeenHandled = true // 이벤트가 처리되었다고 표시한 후에
content // 값을 반환함
}
}
// 이벤트의 처리 여부에 상관 없이 값을 반환
fun peekContent(): T = content
}
2. EventObserver Class 정의
class EventObserver<T>(private val onEventUnhandledContent: (T) -> Unit) : Observer<Event<T>> {
override fun onChanged(event: Event<T>?) {
event?.getContentIfNotHandled()?.let { value ->
onEventUnhandledContent(value)
}
}
}
3. activity_main.xml
- 버튼 클릭 시 viewModel 의 onEvent() 함수 호출
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.android.test.MainViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/submitBtn"
android:layout_width="match_parent"
android:layout_height="@dimen/tab_height"
android:onClick="@{()->viewModel.onEvent()}"
android:text="확인"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
3. MainViewModel.kt
- 발생시킬 이벤트 등록
class MainViewModel @ViewModelInject constructor() : ViewModel() {
private val _event = MutableLiveData<Event<Boolean>>()
val event: LiveData<Event<Boolean>>
get() = _event
fun onEvent() {
_event.value = Event(true)
}
}
4. MainActivity.kt
- DataBinding 을 통한 레이아웃 및 viewModel 등록
- viewModel 의 event 를 observe 등록함으로써 발생하는 이벤트 처리
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityTermBinding
private val viewModel by viewModels<MainViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.viewModel = viewModel
// Set ObserverViewModel
observerViewModel()
}
// Set Observer
fun observerViewModel() {
viewModel.apply {
event.observe(this@MainActivity, EventObserver {
val i = Intent(this@MainActivity, SecondActivity::class.java)
startActivity(i)
})
}
}
}