-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
写了个简版的防止倒灌,不知道行不行 #17
Comments
感谢你的分享,刚刚测试一番,结果符合 “防止倒灌” 的预期,但没有发现 “简化逻辑” 的作用, 它相较于 UnPeekLiveData 的 “防倒灌逻辑” 的不同之处主要体现在: 它在 LiveData 处额外引入了 currentVersion,用作 ObserverProxy onChange 时的内部判断,所以它在 setValue 时无需通过遍历 ObserverProxy 来重置 state。 这是我看到的唯一不同的地方,且某种程度上增加了逻辑的复杂度, 因为目前在 UnPeekLiveData 中,只需盯着 ObserverProxy state 这一变量去发生改变,而上述 EventMutableLiveData 需要在 setValue 时兼顾 currentVersion 的自增、在 Observe 时兼顾 mVersion 的对齐。 最后分享一下 “纯 event 用途” 的情况下,UnPeekLiveData V6.1 的简版设计: public class ProtectedUnPeekLiveData<T> extends LiveData<T> {
private final ConcurrentHashMap<Observer<? super T>, ObserverProxy> observerMap = new ConcurrentHashMap();
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
Observer<? super T> observer1 = getObserverProxy(observer);
if (observer1 != null) {
super.observe(owner, observer1);
}
}
@Override
public void observeForever(@NonNull Observer<? super T> observer) {
Observer<? super T> observer1 = getObserverProxy(observer);
if (observer1 != null) {
super.observeForever(observer1);
}
}
private Observer<? super T> getObserverProxy(Observer<? super T> observer) {
if (observerMap.containsKey(observer)) {
return null;
} else {
ObserverProxy proxy = new ObserverProxy(observer);
observerMap.put(observer, proxy);
return proxy;
}
}
private class ObserverProxy implements Observer<T> {
public final Observer<? super T> target;
public boolean allow;
public ObserverProxy(Observer<? super T> target) {
this.target = target;
}
@Override
public void onChanged(T t) {
if (allow) {
allow = false;
target.onChanged(t);
}
}
}
@Override
protected void setValue(T value) {
for (Map.Entry<Observer<? super T>, ObserverProxy> entry : observerMap.entrySet()) {
entry.getValue().allow = true;
}
super.setValue(value);
}
@Override
public void removeObserver(@NonNull Observer<? super T> observer) {
observerMap.remove(observer);
super.removeObserver(observer);
}
}
|
如果只是防止倒灌的话,其实是简化了的,只使用一个变量维持一个版本号,效率会更高,占用内存更少; |
你可以贴一下 “仅防止倒灌” 且不需要 ObserverMap 的简版设计,不然口头上说的话,我难以核对和理解。 |
public class UnPeekLiveData extends MutableLiveData {
} |
明白了,version 这招真是妙,proxy 的 boolean 遍历来重置,离不开 map, livedata 的 currentVersion 和 proxy 的 version 的对比,还有 Observe 时的保持一致,刚好解决了这个问题, 非常感谢你的这个分享,为此可以邀请你 pull request 上述设计吗?这可以让你的这次分享出现在贡献名单中。开源不是一个人的战斗,我们希望每位贡献者都能出现在贡献者名单中。 |
这样也有问题吧,每次都new ObserverProxy会导致重复监听,最好在ObserverProxy重写equals方法,因为在LiveData中mObservers.putIfAbsent这个方法判断是不是已经存在,最终会通过currentNode.mKey.equals(k)进行比较是否是相同的,所以可以重写ObserverProxy的equal方法如下: |
上述讨论属于对核心思路的交流,仅供参考, 在提交代码时,贡献者已补充了 equals 等逻辑的处理,具体以项目实际最新源码为准。 |
public class EventMutableLiveData extends LiveData {
}
The text was updated successfully, but these errors were encountered: