引用官方 LiveData 介绍
LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.
译:LiveData 是可观察的数据持有者类。与常规的可观察对象不同,LiveData 具有生命周期感知功能,这意味着它遵循其他应用程序组件(例如 Activity ,Fragment 或 Service)的生命周期。这种意识确保 LiveData 仅更新处于活动生命周期状态的应用程序组件观察者。
LiveDataBus 和 EventBus 一样作为消息总线来使用,但实际上它算是一种模式,例如 RxBus 依托于 RxJava 的支持,仅用了不到 30 行代码便可实现一个新的消息总线;而 LiveDataBus 与之类似,依托于官方的 LiveData ,我们便可以自己写出一个消息总线,并且这个消息总线是具有生命周期感知能力的。
object LiveDataBus {
private val bus: MutableMap> = mutableMapOf()
fun with(key: String): MutableLiveData {
if (!bus.containsKey(key)) {
bus[key] = MutableLiveData()
}
return bus[key] as MutableLiveData
}
}
嗯?!这样就完了?对的,使用 Kotlin 的话代码很少很简洁。首先这个 LiveDataBus 是一个单例,内部维护着一个可变 map ,这个 map 通过 key 值来返回相应的 LiveData 对象(如果没有这个对象的话就新建一个放进 map 再返回),而拿到这个对象就可以进行订阅或者发送消息了。
发送消息
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// ...
// post
LiveDataBus.with("from_main")
.value = "From MainActivity."
Thread {
// 非主线程下使用 postValue
LiveDataBus.with("from_main")
.postValue("From MainActivity.")
}.start
}
}
订阅接收消息
class SecondActivity : AppCompatActivity() {
private val observer = Observer {
Log.e(TAG, it)
}
override fun onCreate(savedInstanceState: Bundle?) {
// ...
// 使用 observe 函数进行订阅的话,只会在宿主处于前台的状态才会进行回调,
// 也就是如果 activity 被挂在后台了,那么消息会等到 activity 返回前台
// 时再进行回调,这就是 LiveData 的生命周期感知能力带来的好处。
LiveDataBus.with("from_main")
.observe(this::getLifecycle) {
Log.e(TAG, it)
}
// 但是如果我们希望即使 activity 不在前台也可以收到消息,这时就要使用
// observeForever 这个函数了,使用这种方式订阅相当于忽略宿主的生命周期,
// 任何时刻只要宿主还存活着,就一定会回调消息,缺点是需要自己注册与反注册。
LiveDataBus.with("from_main")
.observeForever(observer)
}
override fun onDestroy() {
// ...
LiveDataBus.with("from_main")
.removeObserver(observer)
}
}
真滴棒,仅仅用了几行代码就实现了一个消息总线,虽然是在 LiveData 的基础上将其发扬光大,但还是牛逼。于是开始投入使用,用着用着突然发现,好像有点不对劲,为什么我一订阅了就马上收到消息了,而且这个消息是在我订阅之前就发出的,坑爹啊......
回顾一下上面遇到的问题,在订阅消息之后立刻就能收到订阅前发出的消息,这种属于粘性消息,用过 EventBus 的都知道,但问题是我们并不需要每次都接收粘性消息呀,如果消息不能准确接收的话那这个消息总线还是正宗的消息总线吗?
出现这个问题的原因: LiveData 内部的 mVersion 属性和 LiveData 内部类 ObserverWrapper 内部的 mLastVersion 属性之间会作比较,在订阅时只要 mLastVersion 小于 mVersion 就会强制推送最新的消息。LiveData 只要调用过 setValue
或者 postValue
都会使 mVersion++
,而不管是 LiveData 或者是 LiveData.ObserverWrapper ,其 version 初始值都是 -1 ,只要用 LiveData 设置了值后它的 mVersion 值无论如何都大于 -1 了,这时再进行订阅就会马上收到最后发出的消息了。
通过阅读源码可以发现,每当我们调用 LiveData.observe
函数时,内部都会创建一个 LiveData.LifecycleBoundObserver ,它是 ObserverWrapper 子类,并且实现了 GenericLifecycleObserver 接口,从名字上看可以知道这是一个绑定宿主生命周期的类。当 LifecycleOwner 的状态发生变化时,会调用 LiveData.LifecycleBoundObserver 的 onStateChanged
函数。
接着在 onStateChanged
函数内部进行判断,如果宿主不是 DESTROYED 状态就调用从 ObserverWrapper 继承过来的 activeStateChanged
函数,如果这个时候 ObserverWrapper 的状态是 active ,就继续调用 LiveData.dispatchingValue
函数。
在 LiveData.dispatchingValue
函数中又会调用 LiveData.considerNotify
函数。
在 LiveData.considerNotify
函数中,可以看到红框中的代码就是根本原因了,如果 ObserverWrapper 的 mLastVersion 小于 LiveData 的 mVersion ,就回调 onChanged()
函数,并且每个新的订阅者其 version 都是 -1 ,LiveData 一旦设置过 value 其 version 都是大于 -1 的,这样直接导致了每注册一个新的订阅者,这个订阅者马上就收到消息,即使这个发布消息的动作发生在订阅之前。
通过阅读源码,终于弄明白了为什么会出现这种问题,那么既然出现了这个问题,就得想办法解决。根据上面的分析,只要在注册一个新的订阅者时把 ObserverWrapper 的 mLastVersion 设置成和 LiveData 的 mVersion 一样即可,看图。
我们直接从红框部分入手,LifecycleBoundObserver 是 ObserverWrapper 子类,创建完之后被放进了 mObservers ,mObservers 是 LiveData 的成员变量(SafeIterableMap
),实际上它是一个链表,从 mObservers 的源码中可以发现有一个 protected 的 get
函数,因此我们可以在调用 observe
的时候通过反射拿到 mObservers 中的 LifecycleBoundObserver ,再把它的 mLastVersion 设置成和 LiveData 一致。
而对于非生命周期感知的 observeForever
函数,函数内部生成的不是 LifecycleBoundObserver ,而是 AlwaysActivityObserver ,并且我们没有机会在 observeForever
调用完成后再去更改 AlwaysActiveObserver 的 mLastVersion ,因为再 observeForever
函数体内,回调就已经发生了,看下图。
对于 observeForever
,既然是在函数体中就发生消息回调的,那么可以写一个自己的 ObserverWrapper ,把真正的回调给包装起来。把我们自己的 ObserverWrapper 传给 observeForever
,然后在回调的前去检查调用栈,如果回调是 observeForever
引起的就不回调真正的订阅者。
object LiveDataBus {
private val bus: MutableMap> = mutableMapOf()
fun with(key: String): BusMutableLiveData {
if (!bus.containsKey(key)) {
bus[key] = BusMutableLiveData()
}
return bus[key] as BusMutableLiveData
}
class BusMutableLiveData : MutableLiveData() {
private val observerMap: MutableMap, Observer<*>> = mutableMapOf()
fun observeSticky(
owner: () -> Lifecycle,
observer: (T) -> Unit
) {
super.observe(owner, observer)
}
fun observeForeverSticky(observer: Observer) {
super.observeForever(observer)
}
override fun observeForever(observer: Observer) {
if (!observerMap.containsKey(observer)) {
observerMap[observer] = ObserverWrapper(observer)
}
super.observeForever(observerMap[observer] as Observer)
}
override fun removeObserver(observer: Observer) {
val realObserver: Observer =
if (observerMap.containsKey(observer)) {
observerMap.remove(observer) as Observer
} else {
observer
}
super.removeObserver(realObserver)
}
override fun observe(
owner: LifecycleOwner,
observer: Observer
) {
super.observe(owner, observer)
try {
hook(observer)
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* 利用反射将 LiveData 的 mVersion 赋值给 ObserverWrapper 的 mLastVersion
*/
@Throws(Exception::class)
private fun hook(observer: Observer<*>) {
// Get wrapper's version.
val liveDataClass = LiveData::class.java
// SafeIterableMap, ObserverWrapper> mObservers
val observersField = liveDataClass.getDeclaredField("mObservers")
observersField.isAccessible = true
val observers = observersField[this]
val observersClass: Class<*> = observers.javaClass
// It's mObservers's get method.
val methodGet = observersClass.getDeclaredMethod("get", Any::class.java)
methodGet.isAccessible = true
val observerWrapperEntry = methodGet.invoke(observers, observer)
var observerWrapper: Any? = null
if (observerWrapperEntry is Map.Entry<*, *>) {
// Now we got observerWrapper.
observerWrapper = observerWrapperEntry.value
}
if (observerWrapper == null) {
throw NullPointerException("Wrapper can not be null!")
}
val observerWrapperParentClass: Class<*>? = observerWrapper.javaClass.superclass
val lastVersionField = observerWrapperParentClass!!.getDeclaredField("mLastVersion")
lastVersionField.isAccessible = true
// Get livedata's version.
val versionField = liveDataClass.getDeclaredField("mVersion")
versionField.isAccessible = true
val version = versionField[this]
// Set wrapper's version.
lastVersionField[observerWrapper] = version
}
}
private class ObserverWrapper(val observer: Observer) : Observer {
override fun onChanged(t: T) {
if (isCallOnObserverForever()) {
return
}
observer.onChanged(t)
}
private fun isCallOnObserverForever(): Boolean {
val stackTrace = Thread.currentThread().stackTrace
for (element in stackTrace) {
if ("androidx.lifecycle.LiveData" == element.className
&& "observeForever" == element.methodName
) {
return true
}
}
return false
}
}
}
在这段源码中,用了 BusMutableLiveData 替换了 MutableLiveData ,并且增加了 2 个订阅粘性消息的函数,毕竟有时确实需要用到粘性消息,不可能赶尽杀绝,而原函数 observe
,observeForever
则统一变成了非粘性订阅。
可以看到相比第一版的 LiveDataBus ,改良版增加了许多代码,因为 version 机制,但反过来一想,如果没有这个 version ,我们一样还是要自己实现粘性订阅的功能,在 Android 帮我们实现了这个功能后,我们再自己增加非粘性订阅的功能,其实都差不多。
总结一下 LiveDataBus 的优缺点:
优点:
observeForever
进行回调。缺点:
在这里,还是先比较一下Rxbus
public class RxBus {
private static volatile RxBus mDefaultInstance;
private RxBus() {
}
public static RxBus getDefault() {
if (mDefaultInstance == null) {
synchronized (RxBus.class) {
if (mDefaultInstance == null) {
mDefaultInstance = new RxBus();
}
}
}
return mDefaultInstance;
}
private final Subject
在RxJava中有个Subject类,它继承Observable类,同时实现了Observer接口,因此Subject可以同时担当观察者和被观察者的角色,使用PublishSubject来创建一个Subject对象PublishSubject只有被订阅后才会把接收到的事件立刻发送给观察者。
在需要接收事件的地方,订阅该Subject对象,之后如果Subject对象接收到事件,则会发射给该观察者,此时Subject对象充当被观察者的角色。
完成了订阅,在需要发送事件的地方将事件发送给之前被订阅的Subject对象,则此时Subject对象作为观察者接收事件,然后会立刻将事件转发给订阅该Subject对象的订阅者,以便观察者处理相应事件,到这里就完成了事件的发送与处理。
最后就是取消订阅的操作了,RxJava中,订阅操作会返回一个Disposable对象,调用Disposable.dispose()以便在合适的时机取消订阅,防止内存泄漏。
public class LiveDataBusX {
//存放订阅者
private Map> bus;
private static LiveDataBusX liveDataBus = new LiveDataBusX();
private LiveDataBusX() {
bus = new HashMap();
}
public static LiveDataBusX getInstance() {
return liveDataBus;
}
//注册订阅者
public synchronized BusMutiableLiveData with(String key, Class type) {
if(!bus.containsKey(key)){
bus.put(key,new BusMutiableLiveData());
}
return (BusMutiableLiveData)bus.get(key);
}
public static class BusMutiableLiveData extends MutableLiveData{
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
super.observe(owner, observer);
hook(observer);
}
private void hook(Observer super T> observer) {
try{
//1.得到mLastVersion
Class liveDataClass=LiveData.class;
Field mObserversFeild=liveDataClass.getDeclaredField("mObservers");
mObserversFeild.setAccessible(true);
//获取到这个成员变量的对象
Object mObserversObject=mObserversFeild.get(this);
//得到map对应的class对象
Class> mObserversClass=mObserversObject.getClass();
//需要执行get方法
Method get=mObserversClass.getDeclaredMethod("get",Object.class);
get.setAccessible(true);
Object invokeEntry=get.invoke(mObserversObject,observer);
Object observerWraper=null;
if(invokeEntry!=null && invokeEntry instanceof Map.Entry){
observerWraper=((Map.Entry)invokeEntry).getValue();
}
if(observerWraper==null){
throw new NullPointerException("observerWraper is null!");
}
//得到ObserveWraper的类对象 ,编译擦除问题
Class> superclass=observerWraper.getClass().getSuperclass();
Field mLastVersion=superclass.getDeclaredField("mLastVersion");
mLastVersion.setAccessible(true);
//2.得到mVersion
Field mVersion=liveDataClass.getDeclaredField("mVersion");
mVersion.setAccessible(true);
//3.mLastVersion填到mVersion中
Object mVersionValue=mVersion.get(this);
mLastVersion.set(observerWraper,mVersionValue);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
在使用这个LiveDataBus的过程中,订阅者会收到订阅之前发布的消息,这是不可接受的,在LifeData这篇文章中,讲述了原因,思路就是在把observerWraper的mLastVersion设置成个liveData的mVersion一样的值。
其他版本LivewDataBus
public final class LiveDataBus {
private final Map> bus;
private LiveDataBus() {
bus = new HashMap<>();
}
private static class SingletonHolder {
private static final LiveDataBus DEFAULT_BUS = new LiveDataBus();
}
public static LiveDataBus get() {
return SingletonHolder.DEFAULT_BUS;
}
public synchronized Observable with(String key, Class type) {
if (!bus.containsKey(key)) {
bus.put(key, new BusMutableLiveData<>(key));
}
return (Observable) bus.get(key);
}
public Observable with(String key) {
return with(key, Object.class);
}
public interface Observable {
// void setValue(T value);
void post(T value);
void postDelay(T value, long delay);
void postDelay(T value, long delay, TimeUnit unit);
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer);
void observeSticky(@NonNull LifecycleOwner owner, @NonNull Observer observer);
void observeForever(@NonNull Observer super T> observer);
void observeStickyForever(@NonNull Observer observer);
void removeObserver(@NonNull Observer super T> observer);
}
private static class BusMutableLiveData extends MutableLiveData implements Observable {
private class PostValueTask implements Runnable {
private Object newValue;
public PostValueTask(@NonNull Object newValue) {
this.newValue = newValue;
}
@Override
public void run() {
setValue((T) newValue);
}
}
@NonNull
private final String key;
private Map observerMap = new HashMap<>();
private Handler mainHandler = new Handler(Looper.getMainLooper());
private BusMutableLiveData(String key) {
this.key = key;
}
public boolean isMainThread() {
return Looper.getMainLooper().getThread() == Thread.currentThread();
}
@Override
public void post(T value) {
if(isMainThread()) setValue(value);
else mainHandler.post(new PostValueTask(value));
}
@Override
public void postDelay(T value, long delay) {
mainHandler.postDelayed(new PostValueTask(value), delay);
}
@Override
public void postDelay(T value, long delay, TimeUnit unit) {
postDelay(value, TimeUnit.MILLISECONDS.convert(delay, unit));
}
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
SafeCastObserver safeCastObserver = new SafeCastObserver(observer);
//保存LifecycleOwner的当前状态
Lifecycle lifecycle = owner.getLifecycle();
Lifecycle.State currentState = lifecycle.getCurrentState();
int observerSize = getLifecycleObserverMapSize(lifecycle);
boolean needChangeState = currentState.isAtLeast(Lifecycle.State.STARTED);
if (needChangeState) {
//把LifecycleOwner的状态改为INITIALIZED
setLifecycleState(lifecycle, Lifecycle.State.INITIALIZED);
//set observerSize to -1,否则super.observe(owner, observer)的时候会无限循环
setLifecycleObserverMapSize(lifecycle, -1);
}
super.observe(owner, safeCastObserver);
if (needChangeState) {
//重置LifecycleOwner的状态
setLifecycleState(lifecycle, currentState);
//重置observer size,因为又添加了一个observer,所以数量+1
setLifecycleObserverMapSize(lifecycle, observerSize + 1);
//把Observer置为active
hookObserverActive(safeCastObserver, true);
}
//更改Observer的version
hookObserverVersion(safeCastObserver);
}
public void observeSticky(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
super.observe(owner, new SafeCastObserver<>(observer));
}
@Override
public void observeForever(@NonNull Observer super T> observer) {
if (!observerMap.containsKey(observer)) {
observerMap.put(observer, new ObserverWrapper(observer));
}
super.observeForever(observerMap.get(observer));
}
public void observeStickyForever(@NonNull Observer observer) {
super.observeForever(observer);
}
@Override
public void removeObserver(@NonNull Observer super T> observer) {
Observer realObserver = null;
if (observerMap.containsKey(observer)) {
realObserver = observerMap.remove(observer);
} else {
realObserver = observer;
}
super.removeObserver(realObserver);
if (!hasObservers()) {
LiveDataBus.get().bus.remove(key);
}
}
private void setLifecycleObserverMapSize(Lifecycle lifecycle, int size) {
if (lifecycle == null) {
return;
}
if (!(lifecycle instanceof LifecycleRegistry)) {
return;
}
try {
Field observerMapField = LifecycleRegistry.class.getDeclaredField("mObserverMap");
observerMapField.setAccessible(true);
Object mObserverMap = observerMapField.get(lifecycle);
Class> superclass = mObserverMap.getClass().getSuperclass();
Field mSizeField = superclass.getDeclaredField("mSize");
mSizeField.setAccessible(true);
mSizeField.set(mObserverMap, size);
} catch (Exception e) {
e.printStackTrace();
}
}
private int getLifecycleObserverMapSize(Lifecycle lifecycle) {
if (lifecycle == null) {
return 0;
}
if (!(lifecycle instanceof LifecycleRegistry)) {
return 0;
}
try {
Field observerMapField = LifecycleRegistry.class.getDeclaredField("mObserverMap");
observerMapField.setAccessible(true);
Object mObserverMap = observerMapField.get(lifecycle);
Class> superclass = mObserverMap.getClass().getSuperclass();
Field mSizeField = superclass.getDeclaredField("mSize");
mSizeField.setAccessible(true);
return (int) mSizeField.get(mObserverMap);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
private void setLifecycleState(Lifecycle lifecycle, Lifecycle.State state) {
if (lifecycle == null) {
return;
}
if (!(lifecycle instanceof LifecycleRegistry)) {
return;
}
try {
Field mState = LifecycleRegistry.class.getDeclaredField("mState");
mState.setAccessible(true);
mState.set(lifecycle, state);
} catch (Exception e) {
e.printStackTrace();
}
}
private Object getObserverWrapper(@NonNull Observer observer) throws Exception {
Field fieldObservers = LiveData.class.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();
}
return objectWrapper;
}
private void hookObserverVersion(@NonNull Observer observer) {
try {
//get wrapper's version
Object objectWrapper = getObserverWrapper(observer);
if (objectWrapper == null) {
return;
}
Class> classObserverWrapper = objectWrapper.getClass().getSuperclass();
Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");
fieldLastVersion.setAccessible(true);
//get livedata's version
Field fieldVersion = LiveData.class.getDeclaredField("mVersion");
fieldVersion.setAccessible(true);
Object objectVersion = fieldVersion.get(this);
//set wrapper's version
fieldLastVersion.set(objectWrapper, objectVersion);
} catch (Exception e) {
e.printStackTrace();
}
}
private void hookObserverActive(@NonNull Observer observer, boolean active) {
try {
//get wrapper's version
Object objectWrapper = getObserverWrapper(observer);
if (objectWrapper == null) {
return;
}
Class> classObserverWrapper = objectWrapper.getClass().getSuperclass();
Field mActive = classObserverWrapper.getDeclaredField("mActive");
mActive.setAccessible(true);
mActive.set(objectWrapper, active);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static class ObserverWrapper implements Observer {
@NonNull
private final Observer observer;
ObserverWrapper(@NonNull Observer observer) {
this.observer = observer;
}
@Override
public void onChanged(@Nullable T t) {
if (isCallOnObserve()) {
return;
}
try {
observer.onChanged(t);
} catch (ClassCastException e) {
e.printStackTrace();
}
}
private boolean isCallOnObserve() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
if (stackTrace != null && stackTrace.length > 0) {
for (StackTraceElement element : stackTrace) {
if ("androidx.lifecycle.LiveData".equals(element.getClassName()) &&
"observeForever".equals(element.getMethodName())) {
return true;
}
}
}
return false;
}
}
private static class SafeCastObserver implements Observer {
@NonNull
private final Observer observer;
SafeCastObserver(@NonNull Observer observer) {
this.observer = observer;
}
@Override
public void onChanged(@Nullable T t) {
try {
observer.onChanged(t);
} catch (ClassCastException e) {
e.printStackTrace();
}
}
}
public static Observable get(@NonNull String key, @NonNull Class type) {
return get().with(key, type);
}
public static Observable get(@NonNull String key) {
return (Observable)get(key, Object.class);
}
public static Observable get(@NonNull Class eventType) {
return get(eventType.getName(), eventType);
}
}
上述代码实现了一个通信总线的全部功能,并且还具有生命周期感知功能,使用起来也及其简单,具体使用如下。
注册订阅:
LiveDataBus.get("test", Boolean.class)
.observe(this, new Observer() {
@Override
public void onChanged(Boolean aBoolean) {
}
});
注意:observe仅更新处于活动生命周期状态的应用程序组件观察者,如果需要不受生命周期的影响,只要数据更新就会收到通知可以使用observeForever,这意味着给定的观察者将接收所有事件,并且永远不会被自动删除。需要手动调用removeObserver(Observer)来停止这个LiveData。
发送消息
LiveDataBus.get("test").post(true);
注意:livedata的setValue只可在主线程下使用,多线程下可使用postValue,当然主线程也可以使用这个。这里实现了自己的post方法,统一判断当前所在线程,调用合适的方式。