Android LiveData crash: Cannot add the same observer with different lifecycles
参考
Android lifecycle library: Cannot add the same observer with different lifecycles
项目场景:
最近项目的直播间中出现了少量的crash
出现在如下位置
liveData.observe(this, {...})
问题描述:
当liveData多次调用observe时, 如果Observer使用lambda, 并且lamba中没有引用非静态变量或方法时, 可能就会出现crash! (为什么是可能, 可以看 后续)
比如: 当出现连点的情况, 重复启动页面时可能会出现此类情况.
原因分析:
crash的根源位置是在
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {...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");}...}
解决方案:
可以看到crash原因是existing已经存在, 但没有attached到lifeCycleOwner时会throw Exception.
由crash error信息中可以推断出来, mObservers.putIfAbsent(observer, wrapper);
putIfAbsent中的key->observer已存在, 也就是这个lambda表达式已经存在于这个map结构中,
lambda大坑:
重复调用一个lambda函数时, 当该lambda中没有引用外部的非静态变量和方法, 会引用上一次的lambda实例
解决办法:
1.在lambda中添加非静态变量或方法的引用
2.不使用lambda, new出来一个Observer就可以啦~
后续:
感觉我的第一篇博客写的不够完美, 我决定重现一下这个bug, 结果整了一下午才重现(还好工作不太忙...), 最终才发现了我这边crash的根本原因 -- >
因为项目中直播间是有后台播放的, 所以liveData没有存放在viewModel中, 而是放在了后台的service中; 当直播间在前台, 又通过某种方式(比如通过点击notification)创建了一个直播间实例后, 这时候再调用
oldLiveData.observer(newLifeCycleOwner, oldObserver),
此时crash就出来啦!!!
oldLiveData是从后台service拿到的之前liveData实例,
newLifeCycleOwner是新直播间实例的lifeCycleOwner,
oldObserver就是lambda导致的, 所以用的是还是之前的实例.
这个时候我们再看下源码:
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {...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);}
observer由于lambda原因导致使用的之前的实例(这里有个小知识点, map.put("key", "newValue"), 如果该key已存在, 则会返回oldValue), 这个时候就会返回上一个直播间中liveData对应的existing, 而existings.isAttachedTo(owner) 实际上调用是这里
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
...
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {super(observer);mOwner = owner;}@Overrideboolean isAttachedTo(LifecycleOwner owner) {return mOwner == owner;}
...
}
这个existings实际上是oldLifeCycleOwner和oldObserver构建的实例,
isArrachedTo 中的mOwner对应的就是oldLifeCycleOwner, owner就是newLifeCycleOwner, 因为两个直播间实例不一样, 所以这两个lifeCycleOwner当然不一样啦! -- >所以在existing.isAttachedTo返回的是false, 这个时候终于就会crash了(啊, 心好累...o(╥﹏╥)o).
记录完毕, 希望这篇文章能够帮到你~^_^
Android LiveData crash: Cannot add the same observer with different lifecycles相关推荐
- Android LiveData
In this tutorial, we'll be discussing the LiveData architectural component in our Android Applicatio ...
- Android livedata原理解析之自己实现一个简单的LiveData
LiveData其实就是通过管理生命周期来实现当视图不可见时不渲染数据,当视图可见时再渲染数据.当在一个Activity发送一个网络请求后,立马切到另一个界面或都按下Home键,使得视图不可见..这个 ...
- Android LiveData组件详解以及LiveDataBus
转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/99749323 本文出自[赵彦军的博客] 一.LiveData简介 LiveDat ...
- Android Native crash 处理案例分享
简介:Android Native crash 处理案例分享 1. 背景 目前 mPaas[1] Android使用Crash SDK对闪退进行的处理,CrashSDK 是 Android 平台上一款 ...
- android 程序崩溃后自动重启,Android 应用Crash 后自动重启的方法小结
前提 首先,我们肯定要在Application里面注册一个CrashHandler,监听应用crash public class TestApplication extends MultiDexApp ...
- Android App Crash详解
Android APP Crash通常是由未捕获的Exception或signal引起app异常退出. 本文主要从以下6个方面分析介绍 Android App Crash App Crash 检测 C ...
- Android APP Crash
Android APP Crash 通常是由未捕获的Exception或signal引起app异常退出. App Crash 检测 Crash 问题 Android vitals 分析 App Cra ...
- Android LiveData Observer 多次调用
使用 Android Architecture Components,出现一个问题,LiveData的观察者Obsever会被多次调用. 我的写法是 private void loadData(Fra ...
- 02.Android崩溃Crash库之App崩溃分析
目录总结 01.抛出异常导致崩溃分析 02.RuntimeInit类分析 03.Looper停止App就退出吗 04.handleApplicationCrash 05.native_crash如何监 ...
最新文章
- 【怎样写代码】函数式编程 -- Lambda表达式(二):C#常用委托
- 再迎利好,BCH开发团队BU融合石墨烯区块传播技术
- (0013)iOS 开发之集成友盟第三方登录
- linux cpuspeed irqbalance 进程 cpu占用过高
- php按时间分组的sql语句,(SQL语句)按指定时间段分组统计
- ARM TK1 安装kinect驱动
- 腾讯智慧交通战略重磅升级 打造以人为中心的未来交通
- Naive Bayes Classifier - 朴素贝叶斯分类器
- 被裁半年后进大厂,他咋做到的?
- sql 查询所有数据库-表-表结构
- 通过AO连接多个EO并进行使用
- vue返回上级并且携带数据_前后端分离之后端返回用户角色信息(vueelementadmin+laravel)...
- zabbix监控nginx连接数
- 学习 Qt 编程的好书推荐
- GIS应用知识解读!
- .NET Core 新手上路
- Android USB 开发
- 2020杭电多校赛 Multi-University Training Contest
- ACM1880魔咒词典
- 2020计算机预推免(保研边缘人) | 重大、北邮、浙大软院、大连理工、华东师范、同济