在Android5.1上 onVisibilityChanged 中的 crash 问题

参考文档: https://www.cnblogs.com/xiaomaomao/p/16648099.html

源码查询网站: AOSPXRef

错误信息

 crash 信息

Attempt to invoke interface method 'java.util.Iterator java.lang.Iterable.iterator()' on a null

object reference

 堆栈信息

代码位置

可见是 mWaveList 调用 forEach 时, iterator 报的空指针, 

让我们来看看 mWaveList 是怎么初始化的

val 也就是 final 类型, 类初始化的时候一定是被 new 出来的, 不可能为 null 啊?

由此想到了类构造方法, 成员变量, 静态变量, 静态方法等初始化时机, 再加上有继承关系的时的顺序!

错误分析

首先分析下错误代码位置, 是在重载 onVisibilityChanged 时抛出的, 难道这个时候 子类 还没有初始化完成?

跟着错误堆栈, 看了下流程,  onVisibilityChanged 首次调用的实际 是在父类的构造器中, 调用顺序如下

View 构造器 -> setFlags(viewFlagValues, viewFlagMasks) -> dispatchVisibilityChanged -> onVisibilityChanged, 

如果当前 view 在初始化时(比如在 xml 中设置为 gone)的 visibility 状态不为 visible, 就会分发这个显示状态变更了, 但! 此时还在执行父类的构造方法, 子类的实例还没有构造出来! 子类的成员变量也还没有初始化!!! 这就是 mWaveList 为 null 的原因!

此问题 仅在 5.1 以下手机上出现, 那就看下实现的区别吧

Android 5.0 

Android 6.0 及以上版本实现

多判断了一个 mAttachInfo, mAttachInfo 则是在 dispatchAttachedToWindow 被赋值, 也就是此时 View 一定是初始化完成了的!

5.0 则没有此判断! 

总结

其实主要需要知道类的加载顺序...直接给一个拷贝的结论:

优先级 1、父类静态成员变量 / 静态代码块

优先级 2、子类静态成员变量 / 静态代码块

优先级 3、父类非静态成员变量 / 父类构造代码块 (创建子类对象必须先调用父类的构造方法,完成父类属性的初始化)

优先级 4、父类构造方法

优先级 5、子类非静态成员变量 / 父类构造代码块

优先级 6、子类构造方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃饱很舒服

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值