【吐血🤮】一次生产环境NPE崩溃的排查记录(下)

简介: 直接说引起NPE的根本原因: rx订阅没有取消,回调时Fragment已经被回收,引用view调更新方法,自然NPE。

页面的话三层嵌套:CustomerFragment → ThirdAgentListFragment → CustomerChildNewFragment


接着模拟崩溃,看日志输出结果分析:


网络异常,图片无法展示
|


不难看出Activity重建的时候把Fragment都恢复了,但是很快又销毁掉了,正常来说恢复Fragment的流程:


onCreateView() → onViewCreated() → onActivityCreated() → 各种初始化操作


这里却直接马上走onDestoryView()也走了onDestory(),发生这个原因其实是replace,看回代码:


网络异常,图片无法展示
|


调用FragmentManager的replace()方法,而正常两个Fragment走的生命周期(未调用addToBackStack):


  • 被替换Fragment:onPause() → onStop() → onDestroyView() → onDestroy() → onDetach()


  • 替换Fragment:onAttach() → onCreate() → onCreateView() → onViewCreated() → onActivityCreated() → onStart() → onResume()


所以,这里的实际逻辑是这样:


恢复的方式创建了Fragment → 创建新的Fragment → 替换掉Fragment → 恢复创建的Fragment被干掉


然后,我在Fragment的onActivityCreated()中又发起了一个请求,那就存在一种情况:请求发出去了,响应还没回来,Fragment就被替换干掉了,这个时候去调已经销毁的Fragment里的View实例,妥妥滴空指针啊!


一种看似取巧的解决方式:savedInstanceState(Bundle) 方法中判断参数是否为空,不为空就不加载请求:


网络异常,图片无法展示
|


当然,治本的方法肯定是从网络请求入手,当Activity或Fragment销毁时,需要把rx的订阅都取消掉,方法就是开头说的几种。


项目都四五年了,竟然一直没爆这个BUG,大概的原因是:


单Activity、多Fragment玩法,没有频繁的replace() Fragment的场景,而且大部分请求都有不可取消的Loading。


排查了一天,原来就是这样一个简单的BUG,前人挖坑,后人填坑,真是一口老血...


不过在排查过程中也收获不少:


  • 了解KAE不用findViewById的原理,以后可以放心使用了;


  • ViewBinding有个大概了解;


  • 对Fragment生命周期的验证(平时都是死记);


  • 了解了一下Activity具体重建机制;


就说这么多,解BUG之路道阻且跻,希望本文对你日常的Debug定位错误有所帮助


相关文章
|
前端开发 JavaScript
前端基础 - JavaScript值Boolean类型的默认转换
前端基础 - JavaScript值Boolean类型的默认转换
117 0
|
存储 SQL 缓存
详解 Apache SkyWalking OAP 的分布式计算
SkyWalking的OAP(Observability Analysis Platform,观测分析平台)是一个用于链路数据的分布式计算系统。 因为它巧妙的设计,使得在链路数据计算和聚合过程中,不需要考虑数据的一致性,也没有事务、分布式锁等概念。 在极端情况下,可能出现链路数据的丢失,但会最大限度保障OAP集群的可用性。咱们来看一下,它是如何设计的,为以后的系统设计和架构提供一些思路。
611 0
|
存储 弹性计算 Linux
2022年阿里云服务器租用价格表(最新收费标准及活动价格表)
本文介绍了阿里云服务器价格的组成,官方报价工具和价格计算器的使用,以及最新活动报价等信息。
39952 0
2022年阿里云服务器租用价格表(最新收费标准及活动价格表)
|
消息中间件 Java 中间件
秒懂消息队列MQ,万字总结带你全面了解消息队列MQ
消息队列是大型分布式系统不可缺少的中间件,也是高并发系统的基石中间件,所以掌握好消息队列MQ就变得极其重要。接下来我就将从零开始介绍什么是消息队列?消息队列的应用场景?如何进行选型?如何在Spring Boot项目中整合集成消息队列。
24065 10
秒懂消息队列MQ,万字总结带你全面了解消息队列MQ
|
Java 开发者 Kotlin
深入理解Kotlin中的伴生对象
【8月更文挑战第31天】
263 0
|
12月前
|
机器学习/深度学习 编解码 监控
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
这篇文章详细介绍了如何使用YOLOv8进行目标检测任务,包括环境搭建、数据准备、模型训练、验证测试以及模型转换等完整流程。
18504 59
目标检测实战(六): 使用YOLOv8完成对图像的目标检测任务(从数据准备到训练测试部署的完整流程)
|
11月前
|
JSON 人工智能 自然语言处理
Way To Prompt系列(1): 为什么大模型连"Strawberry"的"r"都数不对?一招“理由先行”显著提升模型思考能力
本文将从两个常见的大模型翻车问题入手解析这些问题背后体现的大模型技术原理(Tokenization与预测下一个Token),并解释了为什么会导致这些问题,接着我们利用CoT(思维链)方法解决这些问题并基于上述原理试图剖析CoT方法起作用的可能原因,最后提出【理由先行】风格这一简单有效的Prompt Trick。
263 2
|
应用服务中间件 Linux 网络安全
nginx安装的详细教程(包括命令行安装和编译安装)
nginx安装的详细教程(包括命令行安装和编译安装)
|
监控 安全 Java
JVM内存问题之排查Direct Memory泄漏有哪些常用方法
JVM内存问题之排查Direct Memory泄漏有哪些常用方法
493 2