文章目录
上篇文章介绍了 Lifecycle组件,Lifecycle主要用于解决生命周期相关的问题,LiveData是以Lifecycle为基础的拓展,解决了跟数据相关的一些问题,本文呢就来介绍下LiveData的牛逼之处吧。
有生命的LiveData
其实,LiveData从它的英文上看就能有所感触,活着的数据,嗯,我觉得很形象。我们在开发过程中,组件所持有的数据确实一直都是死气沉沉的,数据完全要由我们通过代码去生成,去改变,去传递,数据似乎只有存储信息的作用。但是LiveData的出现,就给好像给数据赋予了生命一样,你会发现,数据能自己做一些事情了!!!
LiveData特征
我们先来了解下LiveData的特征:
- LiveData可以持有数据,它可以被观察,被订阅。当其持有的数据发生变化时,LiveData会“考虑”给它的观察者或者说订阅者们发送通知。
- LiveData可以感知订阅它的组件生命周期。只有组件处于激活状态时,LiveData才会把数据更新通知发送给组件。
注意:上述和下文中将会提到的“组件”,是指实现了LifecycleOwner接口的组件,即使用了Lifecycle组件,一般是指Activity或者Fragment。
LiveData优点
- 促使数据变化和UI界面高度同步:当LiveData的数据发生变化时,它会通知处于激活状态的观察者(组件),观察者们就能及时的相应执行更新UI的处理;
- 强大的数据变化通知机制:由于LiveData能感知组件的生命周期,所以,当组件处于非激活状态时,该组件不会收到LiveData的数据变化通知,这样就能避免一些比较难解决的崩溃问题(比如当我们执行网络请求时,数据还没回调,组件就被销毁了,当数据回调回来时执行更新UI操作就会崩溃)。一旦组件恢复激活状态,LiveData就会把最新的数据变化通知发送给该组件。这样的通知机制真的很合理,很AI~
- 避免内存泄漏:在LiveData“考虑”给其观察者发送通知时,会检查观察的生命周期,当观察者处于DESTORYED状态时,LiveData会主动的清除该观察者,可以很好的避免内存泄漏。
- 能够保护用户数据:这里需要配合另外一个组件ViewModel来实现,此时,我们不会讲用户数据直接存放在组件中,而是放在LiveData中,由ViewModel持有LiveData,ViewModel负责向组件提供LiveData的访问接口,这样就完成了数据和组件的分离,当组件遇到如屏幕方向改变等变化时,就可以直接从ViewModel中重新获取数据并恢复UI,而不需要我们再像以前一样做复杂的数据保护措施(利用onSaveInstanceState方法);
用一用LiveData
上面说了一堆偏概念的东西,脑子发胀,还是用程序猿的语言交流一下吧。
准备工作:添加依赖
dependencies {
def lifecycle_version = "2.0.0"
// ViewModel and LiveData
compile "android.arch.lifecycle:extensions:$lifecycle_version"
}
LiveData的使用方式:
1. 直接使用一些Google定义好的LiveData;
2. 继承LiveData,自己搞一个实现类来用;
直接使用LiveData对象
- 创建LiveData对象实例:(配合ViewModel使用效果更佳)
public class NameViewModel extends ViewModel {
// 创建一个持有String类型数据的LiveData
private MutableLiveData<String> mCurrentName;
// 创建一个持有String类型列表数据的LiveData
private MutableLiveData<List<String>> mNameListData;
// 对外提供访问接口
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<>();
}
return mCurrentName;
}
// 对外提供访问接口
public MutableLiveData<List<String>> getNameList(){
if (mNameListData == null) {
mNameListData = new MutableLiveData<>();
}
return mNameListData;
}
}
MutableLiveData是LiveData的子类,是组件中已经定义好的LiveData实现类之一,源码分析时,我们会介绍到,莫急~
- 创建Observer对象,添加观察者:
public class LiveDataFragment extends Fragment {
private static final String TAG = "LiveDataFragment";
private NameViewModel mNameViewModel;
@BindView(R.id.tv_name)
TextView mTvName;
public static LiveDataFragment getInstance(){
return new LiveDataFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 获取ViewModel
mNameViewModel = ViewModelProviders.of(this).get(NameViewModel.class);
// 订阅LiveData中当前Name数据变化,以lambda形式定义Observer
mNameViewModel.getCurrentName().observe(this,(String name) -> {
mTvName.setText(name);
Log.d(TAG, "currentName: " + name);
});
// 订阅LiveData中Name列表数据变化,以lambda形式定义Observer
mNameViewModel.getNameList().observe(this, (List<String> nameList) -> {
for (String item : nameList) {
Log.d(TAG, "name: " + item);
}
});
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.layout_livedata, container, false);
ButterKnife.bind(this, view);
return view;
}
}
代码中,我们在onCreate()方法中通过LiveData.observe()方法添加观察者,当数据变化时会通过回调方法通知观察者,在lambda表达式中更新当前姓名和打印姓名列表。看上去和Lifecycle用法很相似啊。
- 更新LiveData中的数据:
@OnClick({R.id.btn_change_name, R.id.btn_update_list})
void onClicked(View view){
switch (view.getId()){
case R.id.btn_change_name:
mNameViewModel.getCurrentName().setValue("Jane");
break;
case R.id.btn_update_list:
List<String> nameList = new ArrayList<>();
for (int i = 0; i < 10; i++){
nameList.add("Jane<" + i + ">");
}
mNameViewModel.getNameList().setValue(nameList);
break;
}
}
代码很简单,在两个按钮的点击事件中通过LiveData.setValue()方法来改变LiveData中保存的数据。当点击这两个按钮的时候,我们会发现在onCreate()方法中会收相应到数据改变的回调。一般我们会通过ViewModel来改变数据,这里就偷懒了。
继承LiveData类
public class MyLiveData extends LiveData<Integer> {
private static final String TAG = "MyLiveData";
private static MyLiveData sData;
private WeakReference<Context> mContextWeakReference;
public static MyLiveData getInstance(Context context){
if (sData == null){
sData = new MyLiveData(context);
}
return sData;
}
private MyLiveData(Context context){
mContextWeakReference = new WeakReference<>(context);
}
@Override
protected void onActive() {
super.onActive();
registerReceiver();
}
@Override
protected void onInactive() {
super.onInactive();
unregisterReceiver();
}
private void registerReceiver() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
mContextWeakReference.get().registerReceiver(mReceiver, intentFilter);
}
private void unregisterReceiver() {
mContextWeakReference.get().unregisterReceiver(mReceiver);
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "action = " + action);
if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
int wifiRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
int wifiLevel = WifiManager.calculateSignalLevel(wifiRssi, 4);
sData.setValue(wifiLevel);
}
}
};
}
这个例子中,使用了单例模式,加上LiveData,强强联手,实现了一个资源共享的作用。
我们在onActive()和onInactive()方法中分别注册监听和反注册监听WIFI信号强度广播。然后在广播接收者中更新MyLiveData对象中的数据。需要监听这个广播的地方就不用注册监听这个广播了(组件销毁的时候你还要反注册,很烦),直接通过MyLiveData.getInstance()方法获取LiveData,然后调用observe()方法,通过观察这个LiveData来获取WIFI强度变化信息。代码嘛,我偷懒咯。
onActive(),当处于激活状态的observer个数从0到1时,该方法会被调用。
onInactive() ,当处于激活状态的observer个数从1变为0时,该方法会被调用。
嗯,一顿代码下来,我们发现,正常的流程中,我们要在组件中做数据处理,当组件或者其他某个地方获取到数据或者改变了数据时,我们要通过各种手段通知到组件(回调接口啦,EventBus啦),其实LiveData是帮我们省略了数据变更通知这个环节,让我们将关注点集中在数据处理上,再也不用一层一层的写回调(又名:回调地狱)啦,再也不用写onEvent了。
深入分析
到这里,我们已经对LiveData有了大致了解了,嗯,我们已经了解了它的外表,那么它的内涵呢?
类关系图
这是LiveData的整体类关系图,还是比较简单的。我们来一个个分析下:
- LiveData
我们先大致了解下LiveData里面有什么,我们后面会详细介绍其细节。
// LiveData是一个抽象类,但是没有抽象方法
public abstract class LiveData<T> {
......
// 它维护了一个Map集合,用于存储观察者;
// 这一手和Lifecycle好像啊。。。
private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
......
// 考虑是否派发数据变化通知
private void considerNotify(ObserverWrapper observer) {
......
}
// 最终派发数据变化通知方法
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
......
}
// 添加观察者方法
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
......
}
// 添加永久激活状态观察者
public void observeForever(@NonNull Observer<T> observer) {
......
}
// 移除观察者
public void removeObserver(@NonNull final Observer<T> observer) {
......
}
protected void postValue(T value) {
......
}
// 设置数据
@MainThread
protected void setValue(T value) {
......
}
// 获取数据
@Nullable
public T getValue() {
......
}
......
// onInactive()和 onActive()方法一般是在继承LiveData类时被实现的方法
// 能帮助LiveData在没有任何观察者的情况下释放任何繁重的资源。
protected void onActive() {
}
protected void onInactive() {
}
......
// LifecycleBoundObserver是它的内部类,这个类实现了GenericLifecycleObserver接口(重点哟);
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
......
}
// 私有的抽象类ObserverWrapper,用于包装观察者;
private abstract class ObserverWrapper {
......
}
// 配合observeForever()方法使用,此时,默认观察者永久的处于激活状态,需要手动调用removeObserver()移除该观察者
private class AlwaysActiveObserver extends ObserverWrapper {
......
}
}
- LifecycleBoundObserver
LifecycleBoundObserver,它实现了GenericLifecycleObserver,而GenericLifecycleObserver继承了LifecycleObserver接口。在这里可以回顾下Lifecycle组件相关的内容。当组件(Fragment、Activity)生命周期变化时会通过onStateChanged()方法回调过来。
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
- Observer
Observer接口就是观察者,其中定义了LiveData数据变化的回调方法onChanged()。
/**
* A simple callback that can receive from {@link LiveData}.
*
* @param <T> The type of the parameter
*
* @see LiveData LiveData - for a usage description.
*/
public interface Observer<T> {
/**
* Called when the data is changed.
* @param t The new data
*/
void onChanged(@Nullable T t);
}
- MutableLiveData
LiveData的常用子类,它公开了LiveData的setValve和postValue方法。
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
- MediatorLiveData
继承了MutableLiveData,它可以添加并观察其他LiveData,就是说,MediatorLiveData的观察者,可以收到被MediatorLiveData添加进来的LiveData的数据变化通知,吊炸天,一次性完成了对多个数据的变化监听。
/**
* {@link LiveData} subclass which may observer other {@code LiveData} objects and react on
* {@code OnChanged} events from them.
* <p>
* This class correctly propagates its active/inactive states down to source {@code LiveData}
* objects.
* 这个类可以正确的把他的active/inactive状态传递给他的数据源
* @param <T> The type of data hold by this instance
*/
@SuppressWarnings("WeakerAccess")
public class MediatorLiveData<T> extends MutableLiveData<T> {
// 维护了一个Map集合,用于存储其他数据源(LiveData)
private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
/**
* Starts to listen the given {@code source} LiveData, {@code onChanged} observer will be called
* when {@code source} value was changed.
* <p>
* {@code onChanged} callback will be called only when this {@code MediatorLiveData} is active.
* <p> If the given LiveData is already added as a source but with a different Observer,
* {@link IllegalArgumentException} will be thrown.
*/
@MainThread
public <S> void addSource(LiveData<S> source, Observer<S> onChanged) {
// Source实现了Observer接口,所以可以说是一个观察者
Source<S> e = new Source<>(source, onChanged);
// 存储逻辑和LiveData一样
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()) {
// 如果MediatorLiveData存在激活的观察者,就让LiveData添加观察者Source
e.plug();
}
}
/**
* Stops to listen the given {@code LiveData}.
*
* @param toRemote {@code LiveData} to stop to listen
* @param <S> the type of data hold by {@code source} LiveData
*/
@MainThread
public <S> void removeSource(LiveData<S> toRemote) {
Source<?> source = mSources.remove(toRemote);
if (source != null) {
source.unplug();
}
}
@CallSuper
@Override
protected void onActive() {
// 当MediatorLiveData的观察者数目从0变成1时,就遍历其持有的所有LiveData,让LiveData添加观察者Source
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().plug();
}
}
@CallSuper
@Override
protected void onInactive() {
// 当MediatorLiveData的观察者数目从1变成0时,就遍历其持有的所有LiveData,让LiveData移除观察者Source
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().unplug();
}
}
private static class Source<V> implements Observer<V> {
final LiveData<V> mLiveData;
final Observer<V> mObserver;
int mVersion = START_VERSION;
Source(LiveData<V> liveData, final Observer<V> observer) {
mLiveData = liveData;
mObserver = observer;
}
void plug() {
// 添加观察者Source,Source实现了Observer接口,所以可以被LiveData添加为观察者
// 由于Source不存在生命周期,所以调LiveData.observeForever()方法
mLiveData.observeForever(this);
}
void unplug() {
mLiveData.removeObserver(this);
}
@Override
public void onChanged(@Nullable V v) {
// 当LiveData数据发生变化时,会回调到这里
if (mVersion != mLiveData.getVersion()) {
mVersion = mLiveData.getVersion();
// 此时会直接通知mObserver数据变化了,这个mObserver是通过addSource方法添加进来的观察者
mObserver.onChanged(v);
}
}
}
}
注意:通过代码我们发现,MediatorLiveData里面添加的LiveData,只有在MediatorLiveData的处于active状态时(就是MediatorLiveData存在激活的观察者),LiveData的数据变化才会通知到他们的观察者。
LiveData使用时序图
使用LiveData的过程中主要涉及到的重点有三个:
- 在Fragment/Activity中通过LiveData.observer()添加观察者。
- 根据Fragment/Activity生命周期发生变化,移除观察者或者考虑通知观察者更新数据。
- 调用LiveData的setValue()或postValue()方法后,考虑通知观察者更新数据。
我们来通过源码分析这三个重点。
Point.1 添加观察者
LiveData提供了两种添加观察者的方法:observeForever()、observe()。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
// 将LifecycleOwner对象和Observer对象封装成LifecycleBoundObserver对象
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// putIfAbsent()方法是判断容器中的observer(key)是否有已经和wrapper(value)关联
// 如果已经关联则返回关联值,否则关联并返回wrapper
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
// 最后,添加LifecycleOwner的生命周期观察者
owner.getLifecycle().addObserver(wrapper);
}
@MainThread
public void observeForever(@NonNull Observer<T> observer) {
// 该观察者一直处于激活状态
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
结合上文中的LifecycleBoundObserver源码,LifecycleBoundObserver实现了GenericLifecycleObserver接口,成为生命周期观察者,在observe方法的最后一步,给LifecycleOwner对象添加了观察者,这样我们就实现了LiveData的重要特征:与组件生命周期想关联,LiveData能感知组件生命周期变化。
Point.2 组件生命周期变化引起LiveData启动数据更新流程
LifecycleBoundObserver源码中,当组件(Fragment/Activity)生命周期发生变化时,onStateChanged()方法会被调用。此时,我们会判断组件的生命周期,如果是DESTORYED,就移除观察者。如果不是,我们就调用ObserverWrapper中的activeStateChanged方法,考虑向组件发送数据更新通知。
private abstract class ObserverWrapper {
final Observer<T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
void activeStateChanged(boolean newActive) {
// 组件生命周期变化,不一定激活状态发生变化,
// 如从start -> resume,组件只是状态从STARTED变为RESUMED,但是一直都是激活的,
// 在LifecycleBoundObserver的shouldBeActive()方法中我们看到,
// 只要至少是STARTED状态,都会返回true,也就是激活状态
if (newActive == mActive) {
// 组件激活状态未发生变化,则不派发数据更新
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
// 下面2个if语句,验证了上面我们说的调用onActive()和onInactive()的时机
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {
// 组件处于激活状态,就考虑派发数据更新。
dispatchingValue(this);
}
}
}
这里,我们又看到了LiveData的重要特征:组件生命周期变化时,LiveData会根据组件的状态做出不同的处理,实现了组件销毁时就移除该观察者,组件处于非激活时,不发送通知,组件变为激活态时,再发送通知。
上文中,我们提到,LiveData发送通知时,是考虑,而不是直接发通知,为什么要用考虑呢,我们看下dispatchingValue()方法的具体实现。
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
// initiator 不为空是组件生命周期变化引起的LiveData启动数据变化通知流程
// 所以LiveData只会考虑给指定的观察者发送通知
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
// 此处是,当调用LiveData的setValue或postValue方法时触发的流程
// 此时,LiveData会考虑向其所有的观察者发送通知
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
我们来看下很重要的considerNotify()方法,看看LiveData是如何“考虑”的:
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
// 这里的version是指LiveData所持有的数据的版本号,
// 也就是说LiveData持有的数据发生一次变化,version就会自增,
// 如果观察中数据的版本比此次通知中的数据版本新的话,就不会执行通知
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
// 最终调用观察者接口方法onChanged()方法回调最新的数据给观察者
observer.mObserver.onChanged((T) mData);
}
从源码中我们看到,其实LiveData的“考虑”,其实就是在不断的检查观察者的状态。
Point.3 数据变化引起LiveData启动数据更新流程
LiveData提供了两种改变数据的方法:setValue()和postValue()。区别是setValue()要在主线程中调用,而postValue()既可在主线程也可在子线程中调用。
注意,此时,这两个方法的访问权限都是protected,我们需要通过MutableLiveData来调用。
我们先看setValue()方法的具体实现:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
// 增加数据的版本号
mVersion++;
mData = value;
// 直接调用数据分发方法
dispatchingValue(null);
}
assertMainThread()方法用于判断当前线程是否是主线程,不是就抛出异常。
我们再看下postValue()方法的具体实现:
/**
* Posts a task to a main thread to set the given value. So if you have a following code
* executed in the main thread:
* <pre class="prettyprint">
* liveData.postValue("a");
* liveData.setValue("b");
* </pre>
* The value "b" would be set at first and later the main thread would override it with
* the value "a".
* <p>
* If you called this method multiple times before a main thread executed a posted task, only
* the last value would be dispatched.
*
* @param value The new value
*/
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
// postValue中发送的Runnable对象
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
// 最终还是通过setValue方法来实现数据修改和通知
setValue((T) newValue);
}
};
从官方的注释上我们得知,setValue会立刻执行,postValue方法是向主线程发送了一个设置数据的任务,会被加入到主线程的消息队列中,顺序执行。
转化LiveData
在日常开发中,我们肯定会遇到,我们拿到的数据并不是我们最终想要的,我们需要对这个数据进行加工或者转换。用过RxJava的同学表示这都不是事儿~
所以,Google也提供了一个类来协助我们完成这块工作,那就是Transformations类,在Lifecycle的包下。Transformations中只有两个方法:map() 和 switchMap()。
map()
map方法很好理解,就是将一个LiveData中的值,经过处理后,传递给另外一个LiveData,实现了数据转换。
@MainThread
public static <X, Y> LiveData<Y> map(LiveData<X> source, final Function<X, Y> func) {
// 转换后的LiveData是一个MediatorLiveData
final MediatorLiveData<Y> result = new MediatorLiveData<>();
result.addSource(source, new Observer<X>() {
@Override
public void onChanged(@Nullable X x) {
// func.apply(x)是需要我们自己实现的转换逻辑
result.setValue(func.apply(x));
}
});
return result;
}
switchMap()
从源码上看,switchMap是将对某个LiveData的监听转换成对新的LiveData的监听。和map()还是有很大区别的。
@MainThread
public static <X, Y> LiveData<Y> switchMap(LiveData<X> trigger,
final Function<X, LiveData<Y>> func) {
final MediatorLiveData<Y> result = new MediatorLiveData<>();
// 这里看上去是对trigger的监听,但是trigger的变化不会反馈给观察者
result.addSource(trigger, new Observer<X>() {
LiveData<Y> mSource;
@Override
public void onChanged(@Nullable X x) {
// 要求转换方法返回一个LiveData
LiveData<Y> newLiveData = func.apply(x);
if (mSource == newLiveData) {
return;
}
if (mSource != null) {
result.removeSource(mSource);
}
mSource = newLiveData;
if (mSource != null) {
// trigger发生变化后,最终会导致result添加newLiveData监听
// newLiveData数据变化了,才会引发result回调数据给观察者
result.addSource(mSource, new Observer<Y>() {
@Override
public void onChanged(@Nullable Y y) {
result.setValue(y);
}
});
}
}
});
return result;
}
以上就是对LiveData的整体分析啦,有什么不对的地方,欢迎小伙伴们指正,轻喷~