foreword
LiveData is often used, but it is limited to registering an observer on the page, calling setValue and postValue in the ViewModel and that's all. Today, I decided to go through the LiveData library and found a few things that are not commonly used but very useful.
There are two LiveData core libraries: lifecycle-livedata and lifecycle-livedata-core
LiveData.java
This is the core class of LiveData, all the main logic is located here
I found this observeForever here . This method is rarely used. The observer registered by calling this method will always be in an active state. The Pause and Destroy states of the page are invalid for him, so you need to manually call removeObserver when not in use. Sometimes we need to receive the data sent by LiveData when the page is in the Pause state, then observeForever comes in handy.
public void observeForever(@NonNull Observer<? super T> observer) {
...
}
@MainThread
public void removeObserver(@NonNull final Observer<? super T> observer) {
...
}
@MainThread
public void removeObservers(@NonNull final LifecycleOwner owner) {
...
一步移除页面上所有观察者
}
复制代码
MediatorLiveData.java
- MediatorLiveData.addSource
Multiple LiveData sources can be added through addSource. As long as one of them emits data, MediatorLiveData will trigger and forward the data. When we need to observe multiple sources, we can consider whether we can use MediatorLiveData to gather it into one emission source.
- MediatorLiveData.removeSource
Input sources that have been added can be deleted at any time
LiveData liveData1 = ...;
LiveData liveData2 = ...;
MediatorLiveData liveDataMerger = new MediatorLiveData<>();
liveDataMerger.addSource(liveData1, value -> liveDataMerger.setValue(value));
liveDataMerger.addSource(liveData2, value -> liveDataMerger.setValue(value));
@MainThread
public <S> void removeSource(@NonNull LiveData<S> toRemote) {
Source<?> source = mSources.remove(toRemote);
if (source != null) {
source.unplug();
}
}
复制代码
Transformations.java
- Transformations.distinctUntilChanged
When the LiveData processed by distinctUntilChanged encounters the same value that is transmitted multiple times in a row, it will automatically intercept the value of the shield and the repeated value of the previous transmission, and deduplicate the anti-shake weapon.
MutableLiveData source = new MutableLiveData<Integer>()
MutableLiveData outputSource = Transformations.distinctUntilChanged(source)
复制代码
- Transformations.map
According to the specified Function, the emission value type of the original LiveData can be converted into another type of LiveData
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;
}
复制代码
- Transformations.switchMap
The logic of this function is very convoluted. I haven't found a way to explain it in one sentence. For the time being, I will paste the function source code and the official example of calling this function here, so that everyone can understand and understand together.
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;
}
复制代码
class UserViewModel extends AndroidViewModel {
MutableLiveData<String> nameQueryLiveData = ...
LiveData<List<String>> getUsersWithNameLiveData() {
return Transformations.switchMap(
nameQueryLiveData,
name -> myDataSource.getUsersWithNameLiveData(name));
}
void setNameQuery(String name) {
this.nameQueryLiveData.setValue(name);
}
}
复制代码