案例:个股详情界面失去焦点后发生ANR,必现。
在发生ANR生启用android stuiod profiler, 调用CPU Sample Java Methods 开启cpu 监测一段时间。
结果如下:
由上图可以看到,main 线程中程序一直在执行
查看主线程方法调用情况
从上面两个图可以看出来, 主线程 markState() 方法执行占用CPU高达99.60%,耗时长,则表示一定是此处造成的ANR。
从调用顺序可以看出,是由于StockDataInfoActivity.onStop()方法执行后造成的,这与造成的ANR现象一致,是个股详情界面失去焦点时发生ANR.
markState()方法是Fragment的源码,启动debug模式, 最终发现是该方法循环递归造成的。
原因:项目tragetSdkVersion为28, fragmnet的V4包是28.0.0,在个股详情界面SherlockFragmentActivity 所加载的StockDataInfoFragment所继承的LazyLoadFragment中,在onStop onResume onPasue等生命周期方法中调用了getLifecycler().handleLifecyclerEvent()方法。
@Override
public void onStop() {
super.onStop();
handleLifecycleEvent(Lifecycle.Event.ON_STOP);
}
.......
private void handleLifecycleEvent(Lifecycle.Event event) {
if (mLifecycleRegistry != null) {
mLifecycleRegistry.handleLifecycleEvent(event);
}
}
在26.0.0版本及之前的V4包中的fragment 没有getLifecycle()方法,如果需要使用LifecycleRegistery,则需要自己重写生命周期方法并发送相应的事件;而在26.0.1及以后,源码已经处理了,此时如果在业务代码中,再去发送这些事件,就会导致V4 fragment源码中处理生命周期事件时发生递归,造成死循环。
解决方法:删除 mLifecycleRegistry.handleLifecycleEvent(event) 相关代码即可。
希望对大家有用!!!