반응형
MediatorLiveData란?
LiveData
의 하위 클래스로 다른 LiveData
객체를 Observe
하고 해당 객체의 OnChanged
이벤트를 받습니다.
즉, 하나의 MediatorLiveData에 여러 개의 LiveData를 등록하고 한 번에 핸들링할 수 있습니다.
주요 함수로는
addSource()
: observe할 LiveData와 수행할 로직을 추가removeSource()
: 추가된 LiveData 삭제
MediatorLiveData.java 파일을 살펴보면
public class MediatorLiveData<T> extends MutableLiveData<T> {
private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
MediatorLiveData는 LiveData와 Source를 저장하는 Map을 가지고 있고 MutableLiveData를 상속받기 때문에 값이 변경이 가능합니다.
private static class Source<V> implements Observer<V> {
final LiveData<V> mLiveData;
final Observer<? super V> mObserver;
int mVersion =START_VERSION;
Source(LiveData<V> liveData, final Observer<? super V> observer) {
mLiveData = liveData;
mObserver = observer;
}
void plug() {
mLiveData.observeForever(this);
}
void unplug() {
mLiveData.removeObserver(this);
}
@Override
public void onChanged(@Nullable V v) {
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
mObserver.onChanged(v);
}
}
}
또한 MediatorLiveData.java에 있는 Source 클래스는 LiveData와 onChanged 추상 메서드가 포함된 Observer 인터페이스를 가지고 있습니다.
여기서 Source는 LiveData를 옵져빙하며 변화를 감지했을 때 전달받은 Observer의 onChanged를 호출한다는 것을 알 수 있습니다.
예시 - 로그인 기능 구현
MediatorLiveData를 사용하는 예시로 로그인 시에 아이디와 비밀번호의 입력에 따라 로그인 버튼을 활성화 여부를 MediatorLiveData로 만들어서 실시간으로 확인할 수 있습니다.
class UserViewModel : BaseViewModel() {
private val _userId = MutableLiveData<String>()
val userId: LiveData<String> = _userId
private val _userPassword = MutableLiveData<String>()
val userPassword: LiveData<String> = _userPassword
private val _isPossibleLogin = MediatorLiveData<Boolean>()
val isPossibleLogin: LiveData<Boolean> = _isPossibleLogin
init {
_isPossibleLogin.apply {
addSource(_userId) {
value = checkLogin()
}
addSource(_userPassword) {
value = checkLogin()
}
}
}
private fun checkLogin(): Boolean {
return !(userId.value.isNullOrBlank()) || !(userPassword.value.isNullOrBlank())
}
}
추가적으로 확장 함수를 이용하면 추가되는 조건들도 쉽게 구현이 가능합니다. (addSourceList
)
class UserViewModel : BaseViewModel() {
private val _userId = MutableLiveData<String>()
val userId: LiveData<String> = _userId
private val _userPassword = MutableLiveData<String>()
val userPassword: LiveData<String> = _userPassword
private val _isPossibleLogin = MediatorLiveData<Boolean>()
val isPossibleLogin: LiveData<Boolean> = _isPossibleLogin
init {
_isPossibleLogin.apply {
addSourceList(_userPassword, _userId) {
checkLogin()
}
}
}
private fun checkLogin(): Boolean {
return !(userId.value.isNullOrBlank()) || !(userPassword.value.isNullOrBlank())
}
//확장 함수
private fun <T> MediatorLiveData<T>.addSourceList(
vararg liveDataArgument: MutableLiveData<*>,
onChanged: () -> T
) {
liveDataArgument.forEach {
this.addSource(it) { value = onChanged() }
}
}
}
반응형
'개발 > Android' 카테고리의 다른 글
[Android] DataStore란? (Preference DataStore, Proto DataStore) (1) | 2023.01.19 |
---|---|
[Android] MVVM 패턴 및 Clean Architecture, Android Jetpack 적용 예제 (0) | 2022.11.02 |
[Android] 두 개의 RecyclerView 사이에서 Drag and Drop 구현하기 (2) | 2022.09.17 |
[Android] 런처앱(Launcher app)에서 Widget 생성하기 (0) | 2022.09.01 |
[Android] DataBinding이란? (0) | 2022.08.14 |
댓글