일일 회고
차분히... 천천히...하자..
오늘의 키워드
- SingleLiveEvent
- 트러블 슈팅
SingleLiveEvent
LiveData - View와 ViewModel사이 통신을 편리하게 하기 위해 사용하는 Observable한 객체
View는 ViewModel 의LiveData의 변화를 감지하고 이를 Observing하여 View의 상태를 업데이트 한다.
즉, 화면에 연속적으로 표시 되는 데이터에 적합하다.
여기서, 사용자의 이벤트 같은 것을 생각해보자
버튼 클릭, Snackbar, toast, dialog 등 이벤트에 의해서 발생하는 행위들을 봐보자
이들은 사용자의 행위에 의해 1번씩 클릭 되거나, 발생하는 컴포넌트들이다.
여기서 이것들을 LiveData를 사용하서 observing하면 연속적으로 이벤트가 발생 할 수 있다.
이를 해결 하기 위해 LiveData에서 이벤트의 값을 재설정하는 방법을 택할 수 있다.
아래의 트러블 슈팅에서 내가 처음 적용해봤던 방식인데, 이 방식은 코드가 길어지고 별로 좋지 않은 방법이라고 한다.
그래서 이를 해결 할 수 있는 것으로 SingleLiveEvent가 있었다.
LiveData를 한 번만 관찰하는 SingleLiveEvent를 활용하면 LiveData가 여러 번 Observing되는 것을 막을 수 있다.
SingleLiveEvent 는 call() 메소드를 통해 데이터의 변경을 알리는데, 내부적으로 value = null을 수행해서 데이터 전송 없이 변경을 알릴 수 있다.
SingleLiveEvent에 대한 해석이 있어 남겨본다.
import android.util.Log
import androidx.annotation.MainThread
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import java.util.concurrent.atomic.AtomicBoolean
class SingleLiveEvent<T> : MutableLiveData<T>() {
/**
* 멀티쓰레딩 환경에서 동시성을 보장하는 AtomicBoolean.
* false로 초기화되어 있음
*/
private val pending = AtomicBoolean(false)
/**
* View(Activity or Fragment 등 LifeCycleOwner)가 활성화 상태가 되거나
* setValue로 값이 바뀌었을 때 호출되는 observe 함수.
* pending.compareAndSet(true, false)라는 것은, 위의 pending 변수가
* true면 if문 내의 로직을 처리하고 false로 바꾼다는 것이다.
*
* 아래의 setValue를 통해서만 pending값이 true로 바뀌기 때문에,
* Configuration Changed가 일어나도 pending값은 false이기 때문에 observe가
* 데이터를 전달하지 않는다!
*/
@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 ->
if (pending.compareAndSet(true, false)) {
observer.onChanged(t)
}
})
}
/**
* LiveData로써 들고있는 데이터의 값을 변경하는 함수.
* 여기서는 pending(AtomicBoolean)의 변수는 true로 바꾸어
* observe내의 if문을 처리할 수 있도록 하였음.
*/
@MainThread
override fun setValue(t: T?) {
pending.set(true)
super.setValue(t)
}
/**
* 데이터의 속성을 지정해주지 않아도 call만으로 setValue를 호출 가능
*/
@MainThread
fun call() {
value = null
}
companion object {
private val TAG = "SingleLiveEvent"
}
}
출처:https://zladnrms.tistory.com/146
트러블 슈팅
참고자료
'내일배움캠프 7기 > TIL' 카테고리의 다른 글
내일배움캠프 7기 Android TIL 65일차 (2023.10.26) (1) | 2023.10.27 |
---|---|
내일배움캠프 7기 Android TIL 64일차 (2023.10.25) (0) | 2023.10.25 |
내일배움캠프 7기 Android TIL 62일차 (2023.10.23) (1) | 2023.10.23 |
내일배움캠프 7기 Android TIL 61일차 (2023.10.20) (0) | 2023.10.20 |
내일배움캠프 7기 Android TIL 60일차 (2023.10.19) (0) | 2023.10.19 |