参考

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相关推荐

  1. Android LiveData

    In this tutorial, we'll be discussing the LiveData architectural component in our Android Applicatio ...

  2. Android livedata原理解析之自己实现一个简单的LiveData

    LiveData其实就是通过管理生命周期来实现当视图不可见时不渲染数据,当视图可见时再渲染数据.当在一个Activity发送一个网络请求后,立马切到另一个界面或都按下Home键,使得视图不可见..这个 ...

  3. Android LiveData组件详解以及LiveDataBus

    转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/99749323 本文出自[赵彦军的博客] 一.LiveData简介 LiveDat ...

  4. Android Native crash 处理案例分享

    简介:Android Native crash 处理案例分享 1. 背景 目前 mPaas[1] Android使用Crash SDK对闪退进行的处理,CrashSDK 是 Android 平台上一款 ...

  5. android 程序崩溃后自动重启,Android 应用Crash 后自动重启的方法小结

    前提 首先,我们肯定要在Application里面注册一个CrashHandler,监听应用crash public class TestApplication extends MultiDexApp ...

  6. Android App Crash详解

    Android APP Crash通常是由未捕获的Exception或signal引起app异常退出. 本文主要从以下6个方面分析介绍 Android App Crash App Crash 检测 C ...

  7. Android APP Crash

    Android APP Crash 通常是由未捕获的Exception或signal引起app异常退出. App Crash 检测 Crash 问题 Android vitals 分析 App Cra ...

  8. Android LiveData Observer 多次调用

    使用 Android Architecture Components,出现一个问题,LiveData的观察者Obsever会被多次调用. 我的写法是 private void loadData(Fra ...

  9. 02.Android崩溃Crash库之App崩溃分析

    目录总结 01.抛出异常导致崩溃分析 02.RuntimeInit类分析 03.Looper停止App就退出吗 04.handleApplicationCrash 05.native_crash如何监 ...

最新文章

  1. 【怎样写代码】函数式编程 -- Lambda表达式(二):C#常用委托
  2. 再迎利好,BCH开发团队BU融合石墨烯区块传播技术
  3. (0013)iOS 开发之集成友盟第三方登录
  4. linux cpuspeed irqbalance 进程 cpu占用过高
  5. php按时间分组的sql语句,(SQL语句)按指定时间段分组统计
  6. ARM TK1 安装kinect驱动
  7. 腾讯智慧交通战略重磅升级 打造以人为中心的未来交通
  8. Naive Bayes Classifier - 朴素贝叶斯分类器
  9. 被裁半年后进大厂,他咋做到的?
  10. sql 查询所有数据库-表-表结构
  11. 通过AO连接多个EO并进行使用
  12. vue返回上级并且携带数据_前后端分离之后端返回用户角色信息(vueelementadmin+laravel)...
  13. zabbix监控nginx连接数
  14. 学习 Qt 编程的好书推荐
  15. GIS应用知识解读!
  16. .NET Core 新手上路
  17. Android USB 开发
  18. 2020杭电多校赛 Multi-University Training Contest
  19. ACM1880魔咒词典
  20. 2020计算机预推免(保研边缘人) | 重大、北邮、浙大软院、大连理工、华东师范、同济

热门文章

  1. 工业机器人综合实训考核装置
  2. 【面经】迅游、深科技(长城开发)——C++开发
  3. uml通信图画法_UML通信图参考.ppt
  4. TunesKit Video Repair for Mac(视频修复工具)
  5. 适用于mac的科研论文高等数学公式软件
  6. 为什么不喜欢人工智能建筑设计?
  7. cpa机考计算机功能限制破解,2018年注会机考系统答题辅助功能使用说明
  8. 从零开始编译OpenWrt固件
  9. 移动通信平台的搭建(可语音可视屏可收发短信)
  10. 产业合作打造中国云计算实践通途