본문 바로가기
Android

Single Live Event란 + 사용방법

by kkong93 2023. 6. 12.
반응형

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 메서드를 제공한다. 이벤트를 단 한 번만 처리되도록 할 수 있다.

 

 

반응형

댓글