问题思考
- livedata如何观察数据
- livedata怎么感知生命周期
- 为啥livedata他是粘性数据
1.如何实现数据监听
livedata基本使用是通过observe监听,然后setValue/postValue进行通知,先从主线路开始分析
// 完整写法 new Observer onChanged
MyLiveData.info1.observe(this, object: Observer<String> {
override fun onChanged(t: String?) {
textView.text = t // 更新UI
}
})
MyLiveData.info1.setValue\postValue("我是刷新数据")
看下livedata如何监听数据先。可以看下面代码,重点关注LifecycleBoundObserver,它实际就是lifecycleOwner+observer的包装类(为啥要传lifecycleOwner,实际就是为了监听生命周期,先埋下伏笔)。生成之后用mObservers缓存
// 这部分代码将obser封装,并添加都mObservers作为缓存,
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
// 封装类
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
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;
}
owner.getLifecycle().addObserver(wrapper); // 添加到了lifecycle里了
}
上面是添加了订阅者,那我们再看看怎么触发这个订阅者,从setValue开始看
LiveData.java
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
// 大头主要是这个方法,可以从这个方法反查,主要有2个地方,一个传null(setValue),一个传参数(初始化),
// 初始化的时候也是会调用这个方法,这就是为什么livedata会有粘性
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator); // 初始化的时候调用
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
// 通过setValue 触发,然后告诉订阅者
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
// 触发回调了
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// 感知生命周期,如果是非活跃状态就return
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
// 粘性代码控制条件
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
// 重点代码:就是这代码触发观察者的回调,
observer.mObserver.onChanged((T) mData);
}
可以看到我们通过setValue->dispatchingValue->considerNotify->observer.mObserver.onChanged。这就是数据更新通知回调的整个流程。
if (!observer.shouldBeActive()) 注意看这个代码,为啥我们的livedata感知生命周期,要在onStart\onResume状态才能更新ui,就是这个判断的,下面看看这个代码实现
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() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
}
2. 为啥回到活跃状态,数据能重新触发回调
这个涉及到了lifecycle,LivecycleRegistry内部类OBServerWithState的dispathEvent方法不知道有印象吗,这里重新再弄出来给大家看看
static class ObserverWithState {
State mState;
LifecycleEventObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
//mLifecycleObserver 是不是很熟悉
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
}
LiveData里面有一个LifecycleBoundObserver,这玩意不就是一开始说的对lifecycleOwner+observer的封装吗,并且被lifecycle对象add()了。上面的mLifecycleObserver代码就是LifecycleBoundObserver,那最后又触发了LifecycleBoundObserver下面的onStateChanged()
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super 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);
}
}
// ObserverWrapper.java
private abstract class ObserverWrapper {
final Observer<? super T> mObserver;
boolean mActive;
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;
}
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {
dispatchingValue(this); // 是不是又触发了,
}
}
}
总结下上面代码:实际是通过lifecycle生命周期改变,触发了LifecycleBoundObserver的onStateChanged的方法,接着调用它父类的activeStateChanged(),最后又回到dispatchingValue(this)的方法,又回到第一个步骤的内容了
3.为啥是粘性数据
其实从上面已经看到粘性代码这块了,用直白的话术表达:一个Livedata对象,他先设置了setValue ,mVersion已经自增一次过了。但是还没有添加observer,所以dispatchingValue()遍历observer的时候不满足条件,就没办法调用considerNotify更新数据。
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++; // 自增一次,mVersion默认是-1
mData = value;
dispatchingValue(null);
}
等下一次observer()添加了又重新触发considerNotify,前面知道了mVersion自增过(大于-1),而observer.mLastVersion默认-1 是小于mVersion,所以并没有return出去,而是直接调用了observer.mObserver.onChanged,这就是我们粘性的根本原因
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
// 如果是粘性数据,那么mVersion前面自增过,observer.mLastVersion又没有自增过,所以会直接return
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion; // 这里重新复制
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
4.如何干掉粘性数据
只需要想办法在observer()新增订阅者的时候,吧 observer.mLastVersion和mVersion 搞成一样就可以了。提供一个完整的例子
/**
* 单例模式 去掉黏性事件(有关闭黏性的开关) KT的版本
*/
object OKLiveDataBusKT {
// 存放订阅者
private val bus : MutableMap<String, BusMutableLiveData<Any>> by lazy { HashMap() }
// 暴露一个函数,给外界注册 订阅者关系
@Synchronized
fun <T> with(key: String, type: Class<T>, isStick: Boolean = true) : BusMutableLiveData<T> {
if (!bus.containsKey(key)) {
bus[key] = BusMutableLiveData(isStick)
}
return bus[key] as BusMutableLiveData<T>
}
// Any? 是 Object , * 星投影 KT泛型的? 有点像 Java ?
class BusMutableLiveData<T> private constructor() : MutableLiveData<T>() {
var isStick: Boolean = false
// 次构造
constructor(isStick: Boolean) : this() {
this.isStick = isStick
}
// 我是先执行
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
super.observe(owner, observer) // 这句会执行父类的 // 启用系统的功能 不写就破坏了
if (!isStick) {
hook(observer = observer)
Log.d("derry", "Kotlin版本的 不启用黏性")
} else {
Log.d("derry", "Kotlin版本的 启用黏性")
}
}
private fun hook(observer: Observer<in T>) {
// TODO 1.得到mLastVersion
// 获取到LivData的类中的mObservers对象
val liveDataClass = LiveData::class.java
val mObserversField: Field = liveDataClass.getDeclaredField("mObservers")
mObserversField.isAccessible = true // 私有修饰也可以访问
// 获取到这个成员变量的对象 Any == Object
val mObserversObject: Any = mObserversField.get(this)
// 得到map对象的class对象 private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
val mObserversClass: Class<*> = mObserversObject.javaClass
// 获取到mObservers对象的get方法 protected Entry<K, V> get(K k) {
val get: Method = mObserversClass.getDeclaredMethod("get", Any::class.java)
get.isAccessible = true // 私有修饰也可以访问
// 执行get方法
val invokeEntry: Any = get.invoke(mObserversObject, observer)
// 取到entry中的value is "AAA" is String is是判断类型 as是转换类型
var observerWraper: Any? = null
if (invokeEntry != null && invokeEntry is Map.Entry<*, *>) {
observerWraper = invokeEntry.value
}
if (observerWraper == null) {
throw NullPointerException("observerWraper is null")
}
// 得到observerWraperr的类对象
val supperClass: Class<*> = observerWraper.javaClass.superclass
val mLastVersion: Field = supperClass.getDeclaredField("mLastVersion")
mLastVersion.isAccessible = true
// TODO 2.得到mVersion
val mVersion: Field = liveDataClass.getDeclaredField("mVersion")
mVersion.isAccessible = true
// TODO 3.mLastVersion=mVersion
val mVersionValue: Any = mVersion.get(this)
mLastVersion.set(observerWraper, mVersionValue)
}
}
}