LiveData在设计理念上参考了RxJava。
MediatorLiveData在LiveData的基础上,实现了合并多个LiveData的作用。
可以监听一个或多个LiveData的变化。同时转化数据。
MediatorLiveData也是LiveData, 也可以被监听。接到的是转化后的数据。
基本用法:
从getNameFromServer()取的值是"alan", 而MediatorLiveData做了转化后成了alan gong.
public class MyViewModel extends ViewModel {
private MutableLiveData<String> nameLiveData;
private MediatorLiveData<String> testLiveData;
public MyViewModel() {
testLiveData = new MediatorLiveData<>();
testLiveData.addSource(liveEvent, new Observer<String>() {
@Override
public void onChanged(String s) {
testLiveData.postValue(s + " gong");
}
});
getNameFromServer();
}
public MediatorLiveData<String> getTestLiveData() {
return testLiveData;
}
private void getNameFromServer() {
if (liveEvent == null) {
liveEvent = new MutableLiveData<>();
}
liveEvent.setValue("alan");
}
}
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(LayoutInflater.from(this));
setContentView(binding.getRoot());
ViewModelProvider provider = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory());
MyViewModel myViewModel = provider.get(MyViewModel.class);
binding.setViewModel(myViewModel);
myViewModel.getTestLiveData().observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
textView.setText(s);
}
});
}
}
也可以通过AddSource()添加多个LiveData. 道理也是一样的。
原理解析:
MediatorLiveData 类同样也很简单,只有四个方法和一个内部定义类。
addSource()
removeSource()
onActive()
onInactive()
public class MediatorLiveData<T> extends MutableLiveData<T> {
private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
@MainThread
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
Source<S> e = new Source<>(source, onChanged);
Source<?> existing = mSources.putIfAbsent(source, e);
if (existing != null && existing.mObserver != onChanged) {
throw new IllegalArgumentException(
"This source was already added with the different observer");
}
if (existing != null) {
return;
}
if (hasActiveObservers()) {
e.plug();
}
}
@MainThread
public <S> void removeSource(@NonNull LiveData<S> toRemote) {
Source<?> source = mSources.remove(toRemote);
if (source != null) {
source.unplug();
}
}
@CallSuper
@Override
protected void onActive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().plug();
}
}
@CallSuper
@Override
protected void onInactive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().unplug();
}
}
}
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged)
在addSource的方法签名中,onChanged就是source的间接监听对象。是addSource把它们结合在一起。
addSource把所有添加的LiveData整合到一起放在mSources 里面。
public <S> void removeSource(@NonNull LiveData<S> toRemote)
移出通过addSource添加的LiveData对象
重点是 onActive() 和onInactive()
它们俩把mSource里面的LiveData们,开启/关闭监听。如果MediatorLiveData的状态是Active就开启监听,Inactive就关闭监听。
内部Source类
前面提到addSource里的onChanged是间接监听对象。那么实际直接监听对象就是这个内部类Source. Source对监听到data中转后再发给onChanged。
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);
}
}
}
接下来讲一下Transformations:
MediatorLiveData只是初始封装,实际使用最多的还是Transformations。是在MediatorLiveData基础上实现数据转化,就像RxJava的map和flatMap。
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;
}
}
public interface Function<I, O> {
/**
* Applies this function to the given input.
*
* @param input the input
* @return the function result.
*/
O apply(I input);
}
public static <X, Y> LiveData<Y> map(
@NonNull LiveData<X> source,
@NonNull final Function<X, Y> mapFunction)
就是前面基础使用讲到的方式.
public static <X, Y> LiveData<Y> switchMap(
@NonNull LiveData<X> source,
@NonNull final Function<X, LiveData<Y>> switchMapFunction)
实现了LiveData<Y>到LiveData<X>的转变。
具体的转变过程是开发者在interface Function<I, O>的O apply(I input);里实现。
Transformations使用如下:
LiveData<String> nameLiveData = Transformations.map(myViewModel.liveEvent, new Function<String, String>() {
@Override
public String apply(String input) {
return input + "alan";
}
});
nameLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
textViewName.setText(s);
}
});
LiveData<Integer> agoLiveData = Transformations.switchMap(myViewModel.liveEvent, new Function<String, LiveData<Integer>>() {
@Override
public LiveData<Integer> apply(String input) {
MutableLiveData<Integer> serverData = new MutableLiveData<Integer>();
server.getServerData(serverData);//do business in background, and while get data, raise event.
return serverData; // return first to UI or view model.
}
});
agoLiveData.observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
textViewAge.setText(String.valueOf(integer));
}
});
以上是MediatorLiveData & Transformations的使用场景和原理。