什么是LiveData
官方定义如下:
LiveData是一个可以观察的数据存储类,不同于常规的可观察类,LiveData具有生命周期感知能力,意味着它遵从app组件(比如Activity、Fragment或Service)的生命周期,这种感知能力可确保 LiveData仅更新处于活跃生命周期状态的app组件的观察者。
拆解开来主要有3个方面:
- LiveData是一个数据持有者,给源数据包装一层。
- LiveData具有生命周期感知能力。
- LiveData更新数据只发生在组件(Activity/Fragment/Service)活跃生命周期状态(STARTED、RESUMED)。
使用LiveData的优势:
- 确保UI符合数据的状态,LiveData遵循观察者模式,当对应的数据发生变化时,LiveData会通知Observer对象。你可以在这些Observer对象中更新UI,就不需要每次数据发生改变时更新UI了。
- 没有内存泄露,当关联的组件为DESTROYED状态时,Observer对象自己会回收掉。
- 不会有Activity停止导致的崩溃,如果关联组件的生命周期状态是inactive,比如一个activity进入后台后,它不会再收到任何LiveData事件。
- 数据始终是最新的,如果当前生命周期为inactive,它将在再次变为active状态时接收到最新的数据。比如,一个在后台的Activity在回到前台后马上会接收最新的数据。
- 不再需要手动处理生命周期,UI组件只需要观察对应的数据,LiveData会自动进行管理,因为LiveData可以感知对应组件生命周期的变化。
- 合理的配置更改,如果一个Activity或Fragment由于配置更改导致重建,比如屏幕旋转,重建后马上会收到最新的数据。
- 共享资源,你可以用LiveData结合单例来封装系统服务,这样就可以在应用中共享这个系统服务了。
基本使用
看如下代码:
java
public class MyActivity extends AppCompatActivity {
private static final String TAG = MyActivity.class.getSimpleName();
private MutableLiveData<String> mLiveData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLiveData = new MutableLiveData<>();
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.i(TAG, "onChanged: "+s);
}
});
Log.i(TAG, "onCreate: ");
mLiveData.setValue("onCreate");
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "onStart: ");
mLiveData.setValue("onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "onResume: ");
mLiveData.setValue("onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "onPause: ");
mLiveData.setValue("onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "onStop: ");
mLiveData.setValue("onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy: ");
mLiveData.setValue("onDestroy");
}
}
这里先使用MutableLiveData对String进行了包装,然后使用LiveData的observe()方法把new Observer<String>()添加为观察者,最后使用setValue()更新数据,onChanged()方法就会回调。
进入MyActivity打印如下:
less
MyActivity com.example.test I onCreate:
MyActivity com.example.test I onStart:
MyActivity com.example.test I onChanged: onStart
MyActivity com.example.test I onResume:
MyActivity com.example.test I onChanged: onResume
按Home键键打印如下:
less
MyActivity com.example.test I onPause:
MyActivity com.example.test I onChanged: onPause
MyActivity com.example.test I onStop:
再次进入MyActivity打印如下:
less
MyActivity com.example.test I onStart:
MyActivity com.example.test I onChanged: onStart
MyActivity com.example.test I onResume:
MyActivity com.example.test I onChanged: onResume
退出MyActivity打印如下:
less
MyActivity com.example.test I onPause:
MyActivity com.example.test I onChanged: onPause
MyActivity com.example.test I onStop:
MyActivity com.example.test I onDestroy:
通过上面的打印看到,只有onStart()、onResume()、onPause()之后才有onChanged()方法回调。 这就是LiveData的特性,只更新关联组件活跃生命周期状态(STARTED或RESUMED)的数据。
在上一篇Lifecycle的使用和源码解析有如下代码:
java
//在API 29及以上
static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityPostStarted(@NonNull Activity activity) {
dispatch(activity, Lifecycle.Event.ON_START);
}
@Override
public void onActivityPostResumed(@NonNull Activity activity) {
dispatch(activity, Lifecycle.Event.ON_RESUME);
}
@Override
public void onActivityPrePaused(@NonNull Activity activity) {
dispatch(activity, Lifecycle.Event.ON_PAUSE);
}
@Override
public void onActivityPreStopped(@NonNull Activity activity) {
dispatch(activity, Lifecycle.Event.ON_STOP);
}
}
可以看到在API 29及以上Lifecycle.Event.ON_START和Lifecycle.Event.ON_RESUME分别在onStart()和onResume()之后分发,Lifecycle.Event.ON_PAUSE和Lifecycle.Event.ON_STOP分别在onPause()和onStop()之前分发。
又根据上图,执行onStart()之后分发ON_START,此时所处的状态为STARTED;执行onResume()之后分发ON_RESUME,此时所处的状态为RESUMED;执行onPause()之前分发ON_PAUSE,此时所处的状态为STARTED。在STARTED和RESUMED状态时都会回调onChanged()方法。而onStop()执行之前会分发ON_STOP,此时状态变成CREATED,此时就不会再onChanged()方法了。
另外,还可以使用observeForever(Observer) 方法来添加不需要关联LifecycleOwner的观察者。在这种情况下,观察者会被视为始终处于活跃状态。
继承LiveData
如果observer处于STARTED或RESUMED状态,LiveData会认为observer处于活跃状态。以下示例代码说明了如何继承LiveData类:
java
public class StockLiveData extends LiveData<BigDecimal> {
private StockManager stockManager;
private SimplePriceListener listener = new SimplePriceListener() {
@Override
public void onPriceChanged(BigDecimal price) {
setValue(price);
}
};
public StockLiveData(String symbol) {
stockManager = new StockManager(symbol);
}
@Override
protected void onActive() {
stockManager.requestPriceUpdates(listener);
}
@Override
protected void onInactive() {
stockManager.removeUpdates(listener);
}
}
上例中的重要方法有:
- onActive()方法,当LiveData实例有一个活跃观察者的时候调用,你需要在这里关注股价的变化。
- onInactive()方法,当LiveData实例没有活跃观察者的时候调用,你需要在这里断开与StockManager的联系。
- setValue()方法,这个方法是用来更新LiveData的值的,它会通知所有的活跃观察者。 你可以这样用StockLiveData:
java
public class MyFragment extends Fragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
LiveData<BigDecimal> myPriceListener = ...;
myPriceListener.observe(getViewLifecycleOwner(), price -> {
// Update the UI.
});
}
}
这里observe()方法会把fragment的LifecycleOwner作为第一个参数传入,这样做表示此观察者与LifecycleOwner进行了绑定。observe()方法会添加观察者,组件进入DESTROYED状态会自动移除观察者。
你也可以把上例改成一个单例,这样多个Activity、Fragment或Service就可以共享LiveData实例:
java
public class StockLiveData extends LiveData<BigDecimal> {
private static StockLiveData sInstance;
private StockManager stockManager;
private SimplePriceListener listener = new SimplePriceListener() {
@Override
public void onPriceChanged(BigDecimal price) {
setValue(price);
}
};
@MainThread
public static StockLiveData get(String symbol) {
if (sInstance == null) {
sInstance = new StockLiveData(symbol);
}
return sInstance;
}
private StockLiveData(String symbol) {
stockManager = new StockManager(symbol);
}
@Override
protected void onActive() {
stockManager.requestPriceUpdates(listener);
}
@Override
protected void onInactive() {
stockManager.removeUpdates(listener);
}
}
public class MyFragment extends Fragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
StockLiveData.get(symbol).observe(getViewLifecycleOwner(), price -> {
// Update the UI.
});
}
}
Transform LiveData
如果你想要在分发给observer之前修改LiveData中的数据,或者你可能需要返回一个不同的LiveData实例,你可以使用LiveData提供的Transformations类。
Transformations.map()
,可以对LiveData中的数据进行修改并向下游传递。
java
public class MyActivity extends AppCompatActivity {
private static final String TAG = MyActivity.class.getSimpleName();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MutableLiveData<User> userLiveData = new MutableLiveData<>();
LiveData<String> userName = Transformations.map(userLiveData, new Function<User, String>() {
@Override
public String apply(User user) {
return user.name + " " + user.lastName;
}
});
userName.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d(TAG, "the name is:" + s);
}
});
userLiveData.setValue(new User("Jim", "Green"));
}
static class User{
private String name;
private String lastName;
public User(String name, String lastName){
this.name = name;
this.lastName = lastName;
}
}
}
打印如下:
csharp
MyActivity com.example.test D the name is:Jim Green
Transformations.switchMap()
,可以修改LiveData中的数据,返回一个新的不同的LiveData实例。如下是一个根据地址返回邮编的实例:
java
public class MyActivity extends AppCompatActivity {
private static final String TAG = MyActivity.class.getSimpleName();
private MutableLiveData postCodeLiveData = new MutableLiveData<Integer>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MutableLiveData<String> addressInput = new MutableLiveData();
LiveData<Integer> postalCode = Transformations.switchMap(addressInput, new Function<String, LiveData<Integer>>() {
@Override
public LiveData<Integer> apply(String address) {
return getPostCode(address);
}
});
postalCode.observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer s) {
Log.d(TAG, "the postcode is:" + s.toString());
}
});
addressInput.setValue("Los Angeles");
}
private LiveData<Integer> getPostCode(String address) {
if(TextUtils.equals(address, "New York")){
postCodeLiveData.setValue(10001);
}else if(TextUtils.equals(address, "Los Angeles")){
postCodeLiveData.setValue(90001);
}
return postCodeLiveData;
}
}
打印如下:
csharp
MyActivity com.example.test D the postcode is:90001
观察多个LiveData数据
MediatorLiveData是LiveData的子类,可以用来观察多个LiveData的对象。只要其中任一个LiveData数据发生更改,就会触发MediatorLiveData的onChange()方法。
比如UI显示的数据来自于数据库或网络,你可以把从数据库获取的数据的LiveData和从网络获取的数据的LiveData都添加为MediatorLiveData对象的数据来源,代码如下:
java
public class MyActivity extends AppCompatActivity {
private static final String TAG = MyActivity.class.getSimpleName();
private MutableLiveData postCodeLiveData = new MutableLiveData<Integer>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MutableLiveData<Integer> liveData1 = new MutableLiveData<>();
MutableLiveData<Integer> liveData2 = new MutableLiveData<>();
MediatorLiveData<Integer> liveDataMerger = new MediatorLiveData<>();
liveDataMerger.addSource(liveData1, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
liveDataMerger.setValue(integer);
}
});
liveDataMerger.addSource(liveData2, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
liveDataMerger.setValue(integer);
}
});
liveDataMerger.observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
Log.d(TAG, "the value is:" + integer);
}
});
liveData1.setValue(-1);
liveData2.setValue(1);
}
}
打印如下:
csharp
MyActivity com.example.test D the value is:-1
MyActivity com.example.test D the value is:1
UI只需要观察MediatorLiveData就可以从两个数据源数据的更新。
源码分析
LiveData源码分析
我们从LiveData的observe()方法开始分析:
java
public abstract class LiveData<T> {
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe"); //如果不是主线程,抛异常
//LifecycleOwner是DESTROYED状态,直接返回
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//把owner和observer封装到LifecycleBoundObserver里
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//observer和wrapper分别作为key和value添加到mObservers
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//如果已经存在并且不是与当前LifecycleOwner绑定
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
//如果已经存在并且与当前LifecycleOwner绑定
if (existing != null) {
return;
}
//LifecycleBoundObserver作为owner生命周期的观察者
owner.getLifecycle().addObserver(wrapper);
}
}
首先判断LifecycleOwner的状态,如果是DESTROYED状态就直接返回。然后把owner和observer封装到LifecycleBoundObserver中,LifecycleBoundObserver继承自ObserverWrapper并实现了LifecycleEventObserver接口,而LifecycleEventObserver接口又继承自LifecycleObserver接口。
上面代码第31行通过owner.getLifecycle().addObserver(wrapper)
把LifecycleBoundObserver添加为owner的观察者。那么根据Lifecycle的特性,实现了LifecycleObserver接口并且加入LifecycleOwner的观察者就可以感知或获取LifecycleOwner的状态。
另外,observeForever()方法的代码如下:
java
@MainThread
public void observeForever(@NonNull Observer<? super T> observer) {
assertMainThread("observeForever");
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
和observe()方法类似,只不过添加的观察者一直是活跃状态,这意味着这个观察者会接收所有的事件并且不会自动移除,如果不用了你要手动调用removeObserver()方法移除。
LifecycleBoundObserver代码如下:
java
public abstract class LiveData<T> {
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
//mOwner为STARTED或RESUMED状态时,mOwner活跃
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
//LifecycleOwner是DESTROYED状态,则移除观察者
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
//默认为-1
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
void activeStateChanged(boolean newActive) {
//活跃状态没改变,不处理
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
//判断观察者是活跃状态,进行数据分发
dispatchingValue(this);
}
}
}
@MainThread
void changeActiveCounter(int change) {
//previousActiveCount,以前活跃的观察者数量
int previousActiveCount = mActiveCount;
//mActiveCount,现在活跃的观察者数量
mActiveCount += change;
if (mChangingActiveState) {
return;
}
mChangingActiveState = true;
try {
while (previousActiveCount != mActiveCount) {
boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
previousActiveCount = mActiveCount;
if (needToCallActive) {
onActive();//活跃的观察者数量 由0变为1
} else if (needToCallInactive) {
onInactive();//活跃的观察者数量 由1变为0
}
}
} finally {
mChangingActiveState = false;
}
}
}
从上一篇文章Lifecyle的使用和源码解析中,我们了解到LifecycleOwner的生命周期发生变化时会分发对应的event事件,然后触发观察者的onStateChanged()方法回调。
这里onStateChanged()方法中先判断如果LifecycleOwner是DESTROYED状态,则移除观察者,LiveData自动移除观察者的特点就来源于此。接下来调用其父类ObserverWrapper的activeStateChanged()方法处理这个生命周期状态变化,shouldBeActive()的返回值作为参数,至少是STARTED或RESUMED状态,即为活跃状态。
这里解释一下,由于State枚举按照DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED排列,isAtLeast(STARTED)就表示是STARTED或RESUMED状态。
mActiveCount是指LiveData的活跃观察者数量。活跃的观察者数量由0变为1、由1变为0会分别调用LiveData的onActive()、onInactive()方法。这就是前面提到的继承LiveData
的回调方法。
最后判断如果观察者是活跃状态,调用dispatchingValue(this)进行数据分发,代码如下:
java
public abstract class LiveData<T> {
//用于判断是否正在执行dispatchingValue()方法
private boolean mDispatchingValue;
//用于判断当前分发是否失效
//在分发期间添加了新观察者或分发被取消的情况,需要重新分发
private boolean mDispatchInvalidated;
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
//正在执行dispatchingValue(),直接return
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//initiator不为null,仅通知initiator
if (initiator != null) {
considerNotify(initiator);
initiator = null;
}
//initiator为null,通知mObservers上所有的观察者
else {
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
}
如果传入的参数initiator不为null,仅通知initiator这个观察者;如果initiator为null,将通过遍历mObservers拿到所有的ObserverWrapper。initiator啥时候为空呢?这里先留个疑问。继续看considerNotify()方法:
java
public abstract class LiveData<T> {
private void considerNotify(ObserverWrapper observer) {
//观察者不活跃,直接return
if (!observer.mActive) {
return;
}
// 我们先检查observer.mActive作为判断入口
// 即使observer.mActive为true,但是有可能LifecycleOwner现在已经不活跃了,
// 只不过我们暂时还没有收到对应的event,所以这里还要检查LifecycleOwner是否活跃,
// 发现LifecycleOwner不活跃了,再次调用activeStateChanged()方法,传入false
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
}
代码最后一行的observer.mObserver就是我们调用LiveData的observe()方法传入的第2个参数,最后回调Observer接口的onChanged((T) mData)方法,将保存的数据mData传入,这样就实现了接口回调更新数据。
好了,看完了观察者处理数据的流程,那么LiveData什么时候会通知观察者呢?不用想,数据更新的时候肯定要通知观察者,在主线程更新数据需要我们自己调用setValue()方法,MutableLiveData的代码如下:
scala
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);
}
}
MutableLiveData的setValue()方法会调用LiveData的的setValue()方法,代码如下:
java
public abstract class LiveData<T> {
private volatile Object mData;
private int mVersion;
static final int START_VERSION = -1;
//创建值为value的LiveData
public LiveData(T value) {
mData = value;
mVersion = START_VERSION + 1;
}
//无参的LiveData
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
@MainThread
protected void setValue(T value) {
//必须在主线程执行
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
}
首先检查setValue()是否在主线程执行,不在主线程会报错。然后将mVersion加1,如果调用的是不带参数的LiveData的构造方法,这里mVersion变成0。再把value赋值给mData,然后调用dispatchingValue()方法,传入的参数是null,对应前面提到的initiator为null的场景,即遍历所有观察者进行分发回调。
而postValue()则可以在子线程执行,但是postValue()最终还是调用的setValue()方法,只不过会先把数据从子线程传递到主线程,代码如下:
java
public abstract class LiveData<T> {
final Object mDataLock = new Object();
static final Object NOT_SET = new Object();
private volatile Object mData;
volatile Object mPendingData = NOT_SET;
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
//切换到主线程执行setValue()
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
}
第28行与第17行使用了同一把锁互斥执行,目的就是先通过postValue()方法把value赋值给mPendingData,然后再通过mPostValueRunnable的run()方法把mPendingData赋值给newValue,最后把newValue传给setValue()方法。
Transformations源码分析
最后看看map()方法的源码,switchMap()方法类似。
java
public class 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) {
//关注1
result.setValue(mapFunction.apply(x));
}
});
return result;
}
}
map()方法里面新建了一个MediatorLiveData实例,然后调用了它的addSource()方法:
java
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;
}
//LiveData有活跃的观察者
if (hasActiveObservers()) {
e.plug();
}
}
@MainThread
public <S> void removeSource(@NonNull LiveData<S> toRemote) {
Source<?> source = mSources.remove(toRemote);
if (source != null) {
source.unplug();
}
}
}
addSource()方法里面把liveData和Observer包装成Source,添加到mSources。最后判断如果有活跃的观察者,就调用Source的plug()方法。
java
public class MediatorLiveData<T> extends MutableLiveData<T> {
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);
}
}
}
}
这里plug()方法通过mLiveData.observeForever(this)添加自己为永远的观察者。这里为什么使用这样observeForever()方法呢?因为map()方法的目的是在任意情况下都要监听LiveData数据的改变来进行相应的操作。mLiveData数据改变时,代码中的onChanged()方法就会回调执行,onChange()方法又调用了mObserver.onChanged(v),最终执行关注1处的result.setValue(mapFunction.apply(x))。mapFunction.apply()是用来将X类型转成Y类型的,具体怎么转换需要你自己实现。所以最终返回的result是MediatorLiveData<Y>类型的LiveData并调用了其setValue()方法。这样,调用map()方法第1个参数的setValue()方法,转换后的LiveData的setValue()方法就会相应执行。
类关系图如下:
黏性事件
接下来分析一下LiveData的粘性事件
什么是粘性事件?发射的事件早于注册,可以收到注册之前发射的事件称为粘性事件。
LiveData内部通过一个整数mVersion来记录当前数据的版本号,如下所示:
java
protected void setValue(T value) {
...
mVersion++;
...
}
当我们调用setValue()更新数据的时候,mVersion就会自增。
观察者的包装类ObserverWrapper内部也维护了一个版本号mLastVersion,它记录的是上一次回调的数据的版本,默认值为-1。
如果我们先调用setValue()方法,那么mVersion就会自增变为0,然后注册观察者,此时观察者内部维护的版本号mLastVersion为初始值-1。在considerNotify()方法中observer.mLastVersion >= mVersion就会不成立,onChange()方法会回调,观察者就会收到注册之前发射的数据。
java
private void considerNotify(ObserverWrapper observer) {
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
如何解决粘性问题呢?有以下两种方法:
- 方法1.尽量避免这种情况,合理地设计Activity/Fragment的View Model,Fragment不要绑定Activity的View Model,要有自己独立的View Model,使得LiveData和Fragment同生共死。
- 方法2.使用SingleLiveEvent解决粘性问题。 但这种方法有一个缺点,只能有一个观察者,要考虑自己业务的适用性。
- 方法3.使用hook version的方法。这是没有办法的办法,但是功能适配性却最好,没有了粘性事件问题,这也是LiveDataBus源码中的方式。
方法2的机制是用AtomicBoolean记录setValue()的状态, 当setValue()被调用后,mPending被设置为true,mPending.compareAndSet(true, false)才返回true,observer.onChanged(t)才能执行,代码如下:
java
public class SingleLiveEvent<T> extends MutableLiveData<T> {
private final AtomicBoolean mPending = new AtomicBoolean(false);
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<? super T> observer) {
super.observe(owner, new Observer<T>() {
@Override
public void onChanged(@Nullable T t) {
//CAS执行成功后才可以执行onChanged()方法
//这样只有第一次setValue()后onChanged()方法才会执行
if (mPending.compareAndSet(true, false)) {
observer.onChanged(t);
}
}
});
}
@MainThread
public void setValue(@Nullable T t) {
//setValue()调用后将mPending设置为true
mPending.set(true);
super.setValue(t);
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
public void call() {
setValue(null);
}
}
方法3通过在注册一个新的订阅者时把ObserverWrapper的mLastVersion设置成跟LiveData的 mVersion一致即可,代码如下:
java
public class BusMutableLiveData<T> extends MutableLiveData<T> {
private Map<Observer, Observer> observerMap = new HashMap<>();
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
super.observe(owner, observer);
try {
hook(observer);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void observeForever(@NonNull Observer<T> observer) {
if (!observerMap.containsKey(observer)) {
observerMap.put(observer, new ObserverWrapper(observer));
}
super.observeForever(observerMap.get(observer));
}
@Override
public void removeObserver(@NonNull Observer<T> observer) {
Observer realObserver = null;
if (observerMap.containsKey(observer)) {
realObserver = observerMap.remove(observer);
} else {
realObserver = observer;
}
super.removeObserver(realObserver);
}
private void hook(@NonNull Observer<T> observer) throws Exception {
//get wrapper's version
Class<LiveData> classLiveData = LiveData.class;
Field fieldObservers = classLiveData.getDeclaredField("mObservers");
fieldObservers.setAccessible(true);
Object objectObservers = fieldObservers.get(this);
Class<?> classObservers = objectObservers.getClass();
Method methodGet = classObservers.getDeclaredMethod("get", Object.class);
methodGet.setAccessible(true);
Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);
Object objectWrapper = null;
if (objectWrapperEntry instanceof Map.Entry) {
objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();
}
if (objectWrapper == null) {
throw new NullPointerException("Wrapper can not be bull!");
}
Class<?> classObserverWrapper = objectWrapper.getClass().getSuperclass();
Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");
fieldLastVersion.setAccessible(true);
//get livedata's version
Field fieldVersion = classLiveData.getDeclaredField("mVersion");
fieldVersion.setAccessible(true);
Object objectVersion = fieldVersion.get(this);
//set wrapper's version
fieldLastVersion.set(objectWrapper, objectVersion);
}
}
感谢与参考