반응형
ViewModel과 View 간의 통신을 위한 하나의 방법이다.
LiveData를 이용한 Single Live Event는 LiveData의 장점을 유지하면서 화면 회전같은 불필요한 환경에서 발생하는 문제를 해결할 수 있다.
핵심은 특정 이벤트를 단 한번만 실행하는 경우다. 예를 들어, 사용자에게 특정 메세지를 한 번만 보여주는 UI업데이트와 같은 경우에 유용하다. 화면 회전과 같은 상황에서도 이 메세지는 한 번만 표시된다.
사용하기 위해서는 MutableLiveData를 상속받는 새로운 클래스를 생성해야 한다. 이미 실행 됐는지 추적하고, 이벤트가 실행되지 않았을 경우에만 observer에게 알리는 방식으로 작동한다.
예시
class SingleLiveEvent<T> : MutableLiveData<T>() {
private val pending = AtomicBoolean(false)
@MainThread
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
if (hasActiveObservers()) {
Log.w(TAG, "Multiple observers registered but only one will be notified of changes.")
}
// Observe the internal MutableLiveData
super.observe(owner, Observer<T> { t ->
if (pending.compareAndSet(true, false)) {
observer.onChanged(t)
}
})
}
@MainThread
override fun setValue(t: T?) {
pending.set(true)
super.setValue(t)
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
fun call() {
value = null
}
companion object {
private const val TAG = "SingleLiveEvent"
}
}
pending이라는 AtomicBoolean을 사용해 이벤트가 실행되었는지 여부를 추적한다. observe 메서드에서는 이 pending 변수의 상태를 확인하고, 이벤트가 실행되지 않았을 때만 observer에게 알리도록 한다.
실제 viewmodel에서의 사용방법
class MyViewModel : ViewModel() {
private val _navigateToDetails = SingleLiveEvent<Void>()
val navigateToDetails: LiveData<Void> get() = _navigateToDetails
fun userClickedOnButton() {
_navigateToDetails.call()
}
}
Activity, Fragment에서의 사용방법
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val actionViewModel = ViewModelProviders.of(requireActivity()).get(ActionViewModel::class.java)
actionViewModel.observeOnCreateEvent()
.observe(this, Observer {
it?.takeIf { userVisibleHint }?.getContentIfNotHandled()?.let {
//DO what ever is needed
}
})
}
Event는 SingleLiveEvent의 한 종류이다. 이 클래스는 이벤트의 데이터를 보관하고, 이 데이터가 이미 처리되었는지를 추적한다. 데이터가 처리되지 않았을 경우에만 이 데이트는 getContentInNotHandled 메서드를 제공한다. 이벤트를 단 한 번만 처리되도록 할 수 있다.
반응형
'Android' 카테고리의 다른 글
Android FragmentContainerView Error (0) | 2023.06.16 |
---|---|
Android Compose Card backgroundColor Change (0) | 2023.06.12 |
Android Compose에서 dimens.xml 리소스 사용하는 방법 (0) | 2023.06.10 |
Android Widget 만들기 (0) | 2023.05.27 |
Android Compose에서 LiveData 대신 State, Flow 써야하는 이유 (0) | 2023.05.26 |
댓글