7.1内存泄漏
RebornWolfman opened this issue · comments
当使用 removeObservers(@nonnull final LifecycleOwner owner) 的时候,回调过来已经是ObserverWrapper,又封装了一层,导致没有删除掉。应该是加一个判断,判断回调当前类是否已经是ObserverWrapper的类型,不是才需要包装删除,那时候没有测试想到。
@OverRide
public void removeObserver(@nonnull @NotNull Observer<? super T> observer) {
if (observer.getClass().isAssignableFrom(ObserverWrapper.class)) {
super.removeObserver(observer);
} else {
super.removeObserver(createObserverWrapper(observer, START_VERSION, false));
}
}
感谢反馈,我在 7.1 中是采取了以下方式区分的 Observe 和 ObserveForever 的情况从而规避 7.0 的内存泄漏,
你是指最新 7.1 版本的下述代码仍然存在内存泄漏是吗
@Override
public void removeObserver(@NonNull Observer<? super T> observer) {
if (TextUtils.isEmpty(observer.toString())) {
super.removeObserver(observer);
} else {
super.removeObserver(createObserverWrapper(observer, -1));
}
}
刚刚我为本项目 sample 中的 “多观察者测试” 页面添加了 “removeObservers(owner)” 的测试,基于 7.1 的代码,无法复现 “无法移除” 的问题,
换上 isAssignableFrom 来判断,在 “forever观察者页面” 旋屏重建多次时有一定概率发生内存泄漏(猜测会不会是 isAssignableFrom 性能所致)
具体可拉取最新的 sample 试一试
@Override
public void removeObserver(@NonNull Observer<? super T> observer) {
if (observer.getClass().isAssignableFrom(ObserverWrapper.class)) {
super.removeObserver(observer);
} else {
super.removeObserver(createObserverWrapper(observer, START_VERSION));
}
// if (TextUtils.isEmpty(observer.toString())) {
// super.removeObserver(observer);
// } else {
// super.removeObserver(createObserverWrapper(observer, START_VERSION));
// }
}
我原来没有测试过,我只是看,你那个是用多了一个字符串去过滤Observer,效果是一样的;我使用isAssignableFrom ,
测试了 “forever观察者页面”也试过多次旋转屏幕 ,大概测试了十几分钟,没有发现删除不了的。
仅仅是调试的话,两种方式结果都一样,
区别就在于,快速旋转屏幕、让页面重建的次数多了,isAssignableFrom 这种容易收到 leakCanary 的内存泄漏警告,
要说逻辑的话,isAssignableFrom 这种确实更简便易懂,不用像 7.1 这样,额外给 wrapper 加个 isForever 并且重写 toString 来判断。
为排除潜在的干扰因素,刚刚为 sample 的 ForeverObserve 页面添加了 onDestroy 自动移除 ForeverObserver 的脚本,
经过反复测试,v7.1 的方案和 isAssignableFrom 都无内存泄漏问题,
鉴于 isAssignableFrom 的逻辑更简便易懂,我们基于该方案升级框架到 v7.2 版本,
再次感谢 @RebornWolfman 的分享