LiveDataBus
LiveDataBus是基于LiveData實(shí)現(xiàn)的類似EventBus的消息通信框架谦趣,它是基于LiveData實(shí)現(xiàn)的.
LiveDataBus的優(yōu)點(diǎn)
- LiveData具有的這種可觀察性和生命周期感知的能力
- 使用者不用顯示調(diào)用反注冊(cè)方法,由于LiveData具有生命周期感知能力,所以LiveDataBus只需要調(diào)用注冊(cè)回調(diào)方法座每,而不需要顯示的調(diào)用反注冊(cè)方法前鹅。
- LiveDataBus的實(shí)現(xiàn)極其簡(jiǎn)單,相對(duì)EventBus復(fù)雜的實(shí)現(xiàn)峭梳,LiveDataBus只需要一個(gè)類就可以實(shí)現(xiàn)舰绘。
- LiveDataBus可以減小APK包的大小,由于LiveDataBus只依賴Android官方Android Architecture Components組件的LiveData葱椭,沒有其他依賴捂寿,本身實(shí)現(xiàn)只有一個(gè)類。
LiveDataBus的組成
- 消息
- 消息可以是任何的Object挫以,可以定義不同類型的消息者蠕,如Boolean窃祝、String掐松。也可以定義自定義類型的消息踱侣。
- 消息通道
- LiveData扮演了消息通道的角色,不同的消息通道用不同的名字區(qū)分大磺,名字是String類型的抡句,可以通過名字獲取到一個(gè)LiveData消息通道。
- 消息總線
- 消息總線通過單例實(shí)現(xiàn)杠愧,不同的消息通道存放在一個(gè)HashMap中待榔。
- 訂閱
- 訂閱者通過getChannel獲取消息通道,然后調(diào)用observe訂閱這個(gè)通道的消息流济。
- 發(fā)布
- 發(fā)布者通過getChannel獲取消息通道锐锣,然后調(diào)用setValue或者postValue發(fā)布消息。
LiveDataBus的具體實(shí)現(xiàn)
public final class LiveDataBus {
private final Map<String, BusMutableLiveData<Object>> 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 <T> MutableLiveData<T> with(String key, Class<T> type) {
if (!bus.containsKey(key)) {
bus.put(key, new BusMutableLiveData<>());
}
return (MutableLiveData<T>) bus.get(key);
}
public MutableLiveData<Object> with(String key) {
return with(key, Object.class);
}
private static class ObserverWrapper<T> implements Observer<T> {
private Observer<T> observer;
public ObserverWrapper(Observer<T> observer) {
this.observer = observer;
}
@Override
public void onChanged(@Nullable T t) {
if (observer != null) {
if (isCallOnObserve()) {
return;
}
observer.onChanged(t);
}
}
private boolean isCallOnObserve() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
if (stackTrace != null && stackTrace.length > 0) {
for (StackTraceElement element : stackTrace) {
if ("android.arch.lifecycle.LiveData".equals(element.getClassName()) && "observeForever".equals(element.getMethodName())) {
return true;
}
}
}
return false;
}
}
private static 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);
}
}
}
使用方法
- 注冊(cè)訂閱:
LiveDataBus.get()
.with("tag", String.class)
.observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
}
});
- 發(fā)送消息
LiveDataBus.get().with("tag").setValue(str);