map(), switchMap()
리턴 타입
val userLiveData : LiveData<User> = MutableLiveData(User("Jone", "Doe"))
val userName : LiveData<String> = Transformations.map(userLiveData) { user ->
user.firstName + user.lastName
}
-> 데이터 변환을 처리하는 함수에서 String 타입의 객체를 리턴하면 됩니다. 그러면 map() 내부에서 LiveData<'String'> 타입의 객체를 리턴합니다.
val userLiveData : LiveData<User> = MutableLiveData(User("Jone", "Doe"))
val userName : LiveData<String> = Transformations.switchMap(userLiveData) { user ->
MutableLiveData(user.firstName + user.lastName)
}
-> 데이터 변환을 처리하는 함수에서 LiveData<'String'> 타입의 객체를 리턴해야 합니다.
정적 변환 vs 동적 변환
class MainViewModel {
val viewModelResult = Transformations.map(repository.getDataForUser() { data ->
convertDataToMainUIModel(data)
}
}
-> 데이터 변화가 있을 때 즉각적으로 변환만 하면 되는 경우 map()을 사용할 수 있습니다. LiveData인 source의 변경이 발생하면 데이터가 변환되어 Observer에게 이벤트가 전달됩니다.
class MainViewModel {
val repositoryResult = Transformations.switchMap(userManager.user) { user ->
repository.getDataForUser(user)
}
}
-> LiveData 객체를 리턴하기 때문에 repository.getDataForUser(user)에서 미래에 사용할 LiveData를 리턴하고, 준비가 끝났을 때 repository.getDataForUser(user) 내부에서 변환된 데이터를 이전에 리턴한 LiveData에 업데이트 할 수 있습니다.
단순한 작업 vs 오래 걸리는 작업
라이브러리 코드
public static <X, Y> LiveData<Y> map(
@NonNull LiveData<X> source,
@NonNull final Function<X, Y> mapFunction) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
@Override
public void onChanged(@Nullable X x) {
result.setValue(mapFunction.apply(x));
}
});
return result;
}
@MainThread
public static <X, Y> LiveData<Y> switchMap(@NonNull LiveData<X> trigger,
@NonNull final Function<X, LiveData<Y>> func) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(trigger, new Observer<X>() {
LiveData<Y> mSource;
@Override
public void onChanged(@Nullable X x) {
LiveData<Y> newLiveData = func.apply(x);
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
result.removeSource(mSource);
}
mSource = newLiveData;
if (mSource != null) {
result.addSource(mSource, new Observer<Y>() {
@Override
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}
distinctUntilchanged()