👉 ViewModels and LiveData: Patterns + AntiPatterns – Android Developers – Medium
👉 LiveData beyond the ViewModel — Reactive patterns using Transformations and MediatorLiveData
LiveData をリアクティブに操作できるこのユーティリティメソッド。
LiveData を変換します。
これから返されるLiveData オブジェクトを Observe しておけば、Observer のライフサイクルを考慮しながら、データを変換することができます。lazy に処理され、呼び出しや依存関係の記述なしに、ライフサイクル関連の動作が引き継がれます。
👉 Transformations | android.arch.lifecycle.Transformations | Android Developers
実体は MediatorLiveData のユーティリティ
ソースコードを見てみます。
@SuppressWarnings("WeakerAccess")
public class Transformations {
private Transformations() {
}
@MainThread
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> source,
@NonNull final Function<X, LiveData<Y>> switchMapFunction) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
LiveData<Y> mSource;
@Override
public void onChanged(@Nullable X x) {
LiveData<Y> newLiveData = switchMapFunction.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;
}
}
👉 Cross Reference: Transformations.java
ソースコードより、これは、1:1 の MediatorLiveData を使うための便利ツールです。
class MainViewModel {
val repositoryResult = Transformations.switchMap(userManager.user) { user →
repository.getDataForUser(user)
}
}
複数に変換したい場合は、直接 MediatorLiveData を使うのが良いでしょう。
val liveData1: LiveData<Int> = ...
val liveData2: LiveData<Int> = ...
val result = MediatorLiveData<Int>()
result.addSource(liveData1) { value →
result.setValue(value)
}
result.addSource(liveData2) { value →
result.setValue(value)
}
まとめ
ViewModel 内で、その下にある Repository との間で使います。
View (Activity / Fragment) のライフサイクルにも考慮されています。
ViewModel内で、データの id からその詳細情報の取得をしたり、検索文字列をフィルターとしてデータ抽出したり、などに使うことが多いようです。
👉 MediatorLiveDataとTransformationsでViewModelを効果的に使う