class NoStickLiveData<T> : LiveData<T> {
private var mVersion:Int
//反射拿到父类的field mObservers。
private var mObservers:(Iterable<MutableMap.MutableEntry<Observer<*>, *>>)? = null
private fun requireMObservers() : Iterable<MutableMap.MutableEntry<Observer<*>, *>> {
val mOb = mObservers
if (mOb == null) {
val ob = ReflectionUtils.iteratorGetPrivateFieldValue(this, "mObservers", true)
val nob = ob as Iterable<MutableMap.MutableEntry<Observer<*>, *>>
mObservers = nob
return nob
}
return mOb
}
constructor() {
mVersion = -1
}
constructor(data:T?) : super(data) {
mVersion = 0
}
override fun setValue(value: T?) {
mVersion++
super.setValue(value)
}
/**
* 追加不处理粘性的方式
*/
fun observeUnStick(owner: LifecycleOwner, observer: Observer<in T>) {
super.observe(owner, NoStickWrapObserver(this, observer = observer))
}
fun observeForeverUnStick(observer: Observer<in T>) {
super.observeForever(NoStickWrapObserver(this, observer = observer))
}
fun removeObserverUnStick(observer: Observer<in T>) {
val wrap = findObserverWrap(observer) ?: return
super.removeObserver(wrap)
}
private fun findObserverWrap(observer: Observer<in T>) : Observer<in T>? {
requireMObservers().let { iter->
for ((key, _) in iter) {
val wrap = key as NoStickWrapObserver<*>
if (wrap.observer == observer) {
return wrap as Observer<in T>
}
}
}
return null
}
private class NoStickWrapObserver<T>(val self:NoStickLiveData<T>,
val observer: Observer<in T>) : Observer<T> {
private val version: Int = self.mVersion //标记进入的时候的版本
override fun onChanged(t: T?) {
if (version < self.mVersion) {
observer.onChanged(t)
}
}
}
}
//反射的代码 是java版本的
public static Object iteratorGetPrivateFieldValue(Object instance, String fieldName, boolean ignoreSelf) {
for (Class<?> superClass = ignoreSelf ? instance.getClass().getSuperclass() : instance.getClass();
superClass != null && superClass != Object.class;
superClass = superClass.getSuperclass()) {
try {
Field field = superClass.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(instance);
} catch (NoSuchFieldException | IllegalAccessException e) {
}
}
return null;
}
众所周知,LiveData是粘性的。即,当liveData赋值过(或者初始化默认有值),则当监听observe的瞬间,立刻回调给你的监听函数。
想要破除粘性,我翻阅了一些代码,写的五花八门。我这边也是将我个人的实现方案写在这里。
仔细阅读liveData源码,关键点是mVersion三个变化:
- 空构造体赋值-1
- 有参数构造体赋值0
- 随后setValue每次++
而业务代码注册监听的函数observe(owner, observer) 或者observeForever(observer)
都是经过了包装,
LifecycleBoundObserver(owner, observer)
AlwaysActiveObserver(observer)
都放在了全局变量map,mObservers里面。key就是我们传入的变量observer。
直到removeObserver的时候,通过mObservers.remove(observer)来移除。
因此,类似的,我们只需要继承它,同时也借鉴:
- 也在setValue每次把自定义的版本号mVersion++以表征值的更新;
- 然后我们把用户代码的observe或者observeForever进行一次NoStickWrapObserver包装。只有当version有变大才通知即可;
- 移除的时候,就要考虑了。因为父类中mObservers存储的key,就是我们的NoStickWrapObserver,因此,我们需要将用户的observer,反射拿到父类对象map再找出我们的包装类,再去移除。
本代码的好处,
第一,反射只一次,因为mObservers在LiveData是final的全局变量,不会变化,性能损失可以忽略。
第二,与源代码LiveData的思想高度统一,通过wrap用户的observer存起来的思路。
第三,代码量极少;
第四,最重要的,你如果你想要原来的逻辑的LiveData就按照之前的写法;如果想注册一个后续监听的则调用observeUnStick即可,灵活且方便。