什么是 LiveData
官方定义:LiveData 是一个可以观察的数据存储类,不同于常规的可观察类,LiveData 具有生命周期感知能力,意味着它遵从 App 组件(比如 Activity 、 Fragment 或 Service )的生命周期,这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的 App 组件的观察者。
拆解开来主要有 3 个方面:
- LiveData 是一个数据持有者,给源数据包装了一层。
- LiveData 具有生命周期感知能力。
- LiveData 更新数据只发生在组件( Activity / Fragment / Service )活跃生命周期状态( STARTED 、 RESUMED 状态)。
基本使用
看下面的示例:
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");
}
}
mLiveData 是 MutableLiveData<String> 类型的,这里对源数据 String 进行了包装,在 onCreate() 方法中先创建了 mLiveData 的实例,然后调用了 LiveData 的 observe() 方法,给 observe() 方法传递了两个参数,第一个参数是生命周期拥有者(LifecycleOwner),第二个参数是观察者,这里新建了 Observer<String> 作为观察者,最后在各个生命周期方法中使用 setValue() 更新数据, 通过打印可以看到 onChanged() 方法会跟着回调。
第一次进入 MyActivity 打印如下:
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 键打印如下:
MyActivity com.example.test I onPause:
MyActivity com.example.test I onChanged: onPause
MyActivity com.example.test I onStop:
再次进入 MyActivity 打印如下:
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 打印如下:
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 的使用和源码解析 中有如下代码:
// 在 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 类:
public class StockLiveData extends LiveData<BigDecimal> {
private StockManager stockManager;
private SimplePriceListener listener = new SimplePriceListener() {
@Override
public void onPriceChanged(BigDecimal price) {
// 股价发生变化后执行 setValue()
setValue(price);
}
};
public StockLiveData(String symbol) {
// 创建 StockManager 实例
stockManager = new StockManager(symbol);
}
@Override
protected void onActive() {
// 关注股价的变化
stockManager.requestPriceUpdates(listener);
}
@Override
protected void onInactive() {
// 断开与 StockManager 的联系
stockManager.removeUpdates(listener);
}
}
上例中关键的方法有:
- onActive() 方法,当 LiveData 实例有活跃观察者的时候调用,你需要在这里关注股价的变化。
- onInactive() 方法,当 LiveData 实例没有活跃观察者的时候调用,你需要在这里断开与 StockManager 的联系。
- setValue() 方法,这个方法是用来更新 LiveData 的值的,它会通知所有的活跃观察者。
在 MyFragment 中使用 StockLiveData :
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 -> {
// setValue() 后这里会有回调,可以在这里更新 UI.
});
}
}
这里 observe() 方法会把 fragment 的 LifecycleOwner 作为第一个参数传入,这样做表示此观察者与 LifecycleOwner 进行了绑定。observe() 方法会添加观察者,可以在这里的回调方法中更新 UI。
你也可以把上例改成一个单例,这样多个 Activity、Fragment 或 Service 就可以共享 LiveData 实例:
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);
}
}
并且你可以在 Fragment 中使用它,如下所示:
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.
});
}
}
这样只要有一个生命周期组件( Activity、Fragment 或 Service)处于活跃状态,该生命周期组件就可以收到数据更新的回调。
Transform LiveData
如果你想要在分发给 observer 之前修改 LiveData 中的数据,或者你可能想要返回一个不同的 LiveData 实例,你可以使用 LiveData 提供的 Transformations 类。
Transformations.map(),可以对 LiveData 中的数据进行修改并向下游传递。
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<>();
// 通过 Transformations.map 把 LiveData 封装的数据从 User 改成了 String
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;
}
}
}
打印如下:
MyActivity com.example.test D the name is:Jim Green
Transformations.switchMap(),可以修改 LiveData 中的数据,返回一个新的不同的 LiveData 实例。如下是一个根据地址返回邮编的实例:
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;
}
}
打印如下:
MyActivity com.example.test D the postcode is:90001
观察多个 LiveData 数据
MediatorLiveData 是 LiveData 的子类,可以用来观察多个 LiveData 的对象。只要其中任一个 LiveData 数据发生更改,就会触发 MediatorLiveData 的 onChange() 方法。
比如 UI 显示的数据来自于数据库或网络,你可以把从数据库获取的数据的 LiveData 和从网络获取的数据的 LiveData 都添加为 MediatorLiveData 对象的数据来源,代码如下:
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);
}
}
打印如下:
MyActivity com.example.test D the value is:-1
MyActivity com.example.test D the value is:1
UI 只需要观察 MediatorLiveData 就可以获取从两个数据源的数据的更新。
源码分析
LiveData 源码分析
我们从 LiveData 的 observe() 方法开始分析:
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;
}
// 添加观察者
owner.getLifecycle().addObserver(wrapper);
}
}
在 observe() 方法中判断 LifecycleOwner 的状态,如果已经是 DESTROYED 状态了,就直接返回。然后把 owner 和 observer 封装到 LifecycleBoundObserver 中,observer 是 Observer<? super T> 类型的,Observer 是一个接口:
public interface Observer<T> {
void onChanged(T t);
}
LifecycleBoundObserver 继承自 ObserverWrapper 并实现了 LifecycleEventObserver 接口,而 LifecycleEventObserver 接口又继承自 LifecycleObserver 接口。
上面代码第 30 行通过 owner.getLifecycle().addObserver(wrapper) 把 LifecycleBoundObserver 添加为 owner 的观察者。那么根据 Lifecycle 的特性,实现了 LifecycleObserver 接口并且加入 LifecycleOwner 的观察者就可以感知或获取 LifecycleOwner 的状态。
另外,observeForever()方法的代码如下:
public abstract class LiveData<T> {
@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() 方法类似,只不过添加的观察者是一直活跃的观察者( AlwaysActiveObserver 只需要传 observer 这一个参数,不需要管 LifecycleOwner 的生命周期状态),这意味着这个观察者会接收所有的事件并且不会自动移除,如果不用了你要手动调用 removeObserver() 方法移除。
LifecycleBoundObserver 代码如下:
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);
}
}
}
从上一篇文章 Lifecyle 的使用和源码解析 中,我们了解到 LifecycleOwner 的生命周期发生变化时会分发对应的 event 事件,然后触发观察者的 onStateChanged() 方法回调。
这里 onStateChanged() 方法中先判断,如果 LifecycleOwner 的状态变成 DESTROYED 时,则移除观察者,LiveData 自动移除观察者的特点就来源于此。接下来调用 activeStateChanged() 方法,传入的参数为 shouldBeActive() 的返回值,至少是 STARTED 或 RESUMED 状态,即为活跃状态。
这里解释一下,由于 State 枚举按照 DESTROYED , INITIALIZED , CREATED , STARTED , RESUMED 排列,isAtLeast(STARTED) 就表示是 STARTED 或 RESUMED 状态。
activeStateChanged() 方法来自 LifecycleBoundObserver 的父类 ObserverWrapper :
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);
}
}
}
activeStateChanged() 方法先调用了 changeActiveCounter() 方法,这里的 change 参数要么是 1,要么是 - 1:
void changeActiveCounter(int change) {
// previousActiveCount,以前活跃的观察者数量
int previousActiveCount = mActiveCount;
// mActiveCount,现在活跃的观察者数量(+1 或 -1)
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;
}
}
mActiveCount 是指 LiveData 的活跃观察者数量。活跃的观察者数量由 0 变为 1 、由 1 变为 0 会分别调用 LiveData 的 onActive()、onInactive() 方法。这就是前面提到的继承LiveData的回调方法。
回到前面,判断如果观察者是活跃状态,调用 dispatchingValue(this) 进行数据分发,代码如下:
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() 方法:
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 的代码如下:
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() 方法,代码如下:
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 默认为 -1 。再把 value 赋值给 mData ,然后调用 dispatchingValue() 方法,传入的参数是 null,对应前面提到的 initiator 为 null 的场景,即遍历所有观察者进行分发回调。
而 postValue() 则可以在子线程执行,但是 postValue() 最终还是调用的 setValue() 方法,只不过会先把数据从子线程传递到主线程,代码如下:
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 ,这样就把子线程的 value 赋值给了主线程的 newValue,最后把 newValue 传给 setValue() 方法。
总结一下:
- 调用 LiveData 的 observe() 方法时,就把 LifecycleOwner 和 Observer 接口封装成了一个观察者:LifecycleBoundObserver, 并添加到了 mObservers (一个 SafeIterableMap 用于缓存观察者)中,然后调用了 getLifecycle().addObserver() 添加了这个观察者,这意味着这个观察者可以感知和获取 LifecycleOwner 的状态。
- 当你调用 LiveData 的 setValue() 时,然后调用 dispatchValue(null) ,会遍历 mObservers 中所有的观察者,对每个观察者调用 considerNotify(observer),在 considerNotify() 方法中调用 Observer 接口的 onChanged() 方法并将值传入,这样就完成了 setValue() 到 onChanged() 的接口回调更新数据。
- 由于第 1 步中将 LifecycleBoundObserver 添加为 LifecycleOwner 的观察者,当发现 LifecycleOwner 变成 DESTROYED 状态时,会自动移除观察者,避免内存泄漏。
- 当 LifecycleOwner 从 CREATED/STOPPED 等非活跃状态变为 STARTED/RESUMED(活跃状态)时,LifecycleBoundObserver 会收到 onStateChanged() 回调。若新状态是活跃的,且 LiveData 有最新值(mVersion > mLastVersion),则触发 considerNotify()。从而调用 onChanged() 回调,将最新的值重新发送给刚激活的观察者。这就是 LiveData 的“粘性”特性(sticky event):新激活的观察者能立即收到最新数据。
总结一下使用 LiveData 的优势:
- 确保 UI 符合数据的状态,LiveData 遵循观察者模式,当对应的数据发生变化时,LiveData 会通知 Observer 对象。你可以在这些 Observer 对象中更新 UI ,就不需要每次数据发生改变时自己调用方法更新 UI 了。
- 没有内存泄露,当关联的组件变成 DESTROYED 状态时, Observer 对象自己会回收掉。
- 不会有 Activity 停止导致的崩溃,如果关联组件的生命周期状态是 inactive ,比如一个 Activity 进入后台后,它不会再收到任何 LiveData 事件。
- 数据始终是最新的,如果当前生命周期为 inactive ,它将在再次变为 active 状态时接收到最新的数据。比如,一个在后台的 Activity 在回到前台后马上会接收最新的数据。
- 不再需要手动处理生命周期, UI 组件只需要观察对应的数据, LiveData 会自动进行管理,因为 LiveData 可以感知对应组件生命周期的变化。
- 合理的配置更改,如果一个 Activity 或 Fragment 由于配置更改导致重建,比如屏幕旋转,重建后马上会收到最新的数据。
- 共享资源,你可以用 LiveData 结合单例来封装系统服务,这样就可以在应用中共享这个系统服务了。
Transformations源码分析
最后看看 map() 方法的源码, switchMap() 方法类似。
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;
}
}
/**
* 将input转换成output
*/
public interface Function<I, O> {
O apply(I input);
}
map() 方法里面新建了一个 MediatorLiveData 实例,然后调用了它的 addSource() 方法:
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() 方法。
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 的粘性事件(Sticky Event)。
什么是粘性事件?粘性事件是指当一个事件已经发送,但新的观察者订阅时,依然会接收到这个事件的行为。
看下面的示例,先新建一个单例类,单例类中持有一个 MutableLiveData<String> 类型的数据 msg:
public class MyLiveData {
private static MyLiveData mInstance;
public static MyLiveData getInstance() {
if (mInstance == null) {
mInstance = new MyLiveData();
}
return mInstance;
}
private MutableLiveData<String> msg = new MutableLiveData<>();
public MutableLiveData<String> getMsg() {
return msg;
}
}
然后新建一个 FirstActivity,在 onCreate() 中调用 msg 的 observe() 方法,点击按钮的时候会调用 msg 的 setValue() 并跳转到 SecondActivity:
public class FirstActivity extends AppCompatActivity {
private static final String TAG = FirstActivity.class.getSimpleName();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
Button btnJump = findViewById(R.id.btn_jump);
btnJump.setOnClickListener(v -> {
MyLiveData.getInstance().getMsg().setValue("Hello World!!!");
FirstActivity.this.startActivity(new Intent(FirstActivity.this, SecondActivity.class));
});
// 监听
MyLiveData.getInstance().getMsg().observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d(TAG, "Data changed:" + s);
}
});
}
}
再新建一个 SecondActivity,在 SecondActivity 中也调用 msg 的 observe() 方法:
public class SecondActivity extends AppCompatActivity {
private static final String TAG = SecondActivity.class.getSimpleName();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
// 监听
MyLiveData.getInstance().getMsg().observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
Log.d(TAG, "Data changed:" + s);
}
});
}
}
当跳转到 SecondActivity 时,可以看到两个地方都会打印:Data changed:Hello World!!!
粘性问题产生的原因是什么呢? 因为 LiveData 会缓存最新的值,后面加入的观察者也会立即收到这个数据。
通过反射解决
可以通过反射来解决粘性事件。LiveData 内部使用 mVersion 来记录数据变更次数,初始值为 -1 ,如下所示:
public abstract class LiveData<T> {
static final int START_VERSION = -1;
static final Object NOT_SET = new Object();
private volatile Object mData = NOT_SET;
private int mVersion = START_VERSION;
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
}
当我们调用 setValue() 更新数据的时候, mVersion 就会自增。
观察者的包装类 ObserverWrapper 内部也维护了一个版本号 mLastVersion ,它记录的是这个观察者最后一次接收到的数据版本号,默认值为 -1 。
我们先调用 setValue() 方法更新数据,mVersion 会自增变为 0 。进入 SecondActivity 后添加了一个新的观察者,SecondActivity 从非活跃状态变成活跃状态,onStateChanged() 方法会执行,会调用 considerNotify() 方法,参数为当前新添加的观察者 observer。considerNotify() 方法中 observer.mLastVersion >= mVersion 不成立,onChanged() 方法就会回调,观察者就会收到之前调用 setValue() 缓存的数据。
那么如何利用反射解决粘性问题呢?在调用 observe() 方法时,让 observer.mLastVersion 等于 mVersion 即可,代码如下:
public class BusMutableLiveData<T> extends MutableLiveData<T> {
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
super.observe(owner, observer);
try {
hook(observer);
} catch (Exception e) {
e.printStackTrace();
}
}
private void hook(@NonNull Observer<? super T> observer) throws Exception {
// get wrapper's version
Class<LiveData> classLiveData = LiveData.class;
// 拿到 LiveData 的成员变量 mObservers
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);
// 通过 get() 方法拿到 Entry<K, V>
Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);
Object objectWrapper = null;
if (objectWrapperEntry instanceof Map.Entry) {
// 通过 getValue() 拿到 value,value 即观察者 LifecycleBoundObserver
objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();
}
if (objectWrapper == null) {
throw new NullPointerException("Wrapper can not be null!");
}
// 获取 LifecycleBoundObserver的父类 ObserverWrapper
Class<?> classObserverWrapper = objectWrapper.getClass().getSuperclass();
// 拿到 mLastVersion
Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");
fieldLastVersion.setAccessible(true);
// 拿到 LiveData 中的 mVersion
Field fieldVersion = classLiveData.getDeclaredField("mVersion");
fieldVersion.setAccessible(true);
Object objectVersion = fieldVersion.get(this);
// 修改 ObserverWrapper 中 mLastVersion 的值为 mVersion
fieldLastVersion.set(objectWrapper, objectVersion);
}
}
这里通过反射修改 mLastVersion 的值,让其等于 mVersion。
使用的时候在 MyLiveData 中把 msg 改成 BusMutableLiveData<String> 类型:
private BusMutableLiveData<String> msg = new BusMutableLiveData<>();
这样就算你先调用 LiveData 的 setValue() 方法让 LiveData 中的 mVersion 自增变成 0,当你调用 BusMutableLiveData 的 observe() 方法时,会把 ObserverWrapper 的 mLastVersion 也变成 0,这样 observer.mLastVersion >= mVersion 条件成立, onChanged() 方法就不会回调。只有先调用 BusMutableLiveData 的 observe() 方法,再调用 setValue() 方法才会触发回调。
虽然利用反射可以达到目的,但是如果以后 LiveData 源码改了,反射可能会失效或抛出异常,并且反射存在一定的性能开销,所以不推荐这种做法。
SingleLiveEvent
官方推荐使用 SingleLiveEvent 来解决粘性问题,但是 SingleLiveEvent 只适合调用一次 setValue() 只触发一次 onChanged() 的场景。其机制是用 AtomicBoolean 记录 setValue() 的状态, 当setValue() 被调用后,mPending 被设置为true,mPending.compareAndSet(true, false) 返回 true,同时会将 mPending 置为 false,observer.onChanged(t) 才会执行。下次还是要先执行 setValue() 将 mPending 被设置为 true 后,observer.onChanged(t) 才会执行。代码如下:
public class SingleLiveEvent<T> extends MutableLiveData<T> {
private static final String TAG = SingleLiveEvent.class.getSimpleName();
private final AtomicBoolean mPending = new AtomicBoolean(false);
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<? super T> observer) {
if (hasActiveObservers()) {
Log.w(TAG, "Multiple observers registered but only one will be notified of changes.");
}
// Observe the internal MutableLiveData
super.observe(owner, new Observer<T>() {
@Override
public void onChanged(@Nullable T t) {
// 只有 setValue() 后 observer.onChanged() 才会执行,
// 同时 mPending 会更新为 false
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);
}
}
这样通过添加 AtomicBoolean,在调用 SingleLiveEvent 的 setValue() 后才会通知 observer,但是从代码中的注释也可以看到,这种做法多个 observer 只有一个的用户回调被执行,在一对一的情况下通常没啥问题,但是碰到一对多的情况就不适用了,并且 SingleLiveEvent 不支持 Lifecycle 重建后的状态恢复(比如配置变更导致 Activity 重建)。
需要强调的是,粘性不一定是 bug,有时反而是优势,比如粘性让配置变更后可以恢复 UI 状态,是否 “去粘性” 应根据业务场景决定。
感谢与参考