代码改变世界

activity抢占,onStop延后10s执行

2019-11-15 17:38  指针空间  阅读(1131)  评论(0编辑  收藏  举报

场景描述:

电视使用播放器播放音乐,启动另外的activity后,前一个音频播放还需要播放很久(10s左右)

 

问题分析:

音乐播放的activity,在onstop时候,才去释放播放器。activity抢占音乐播放器activity时候,onstop没有马上回调,大概过了10s钟左右才回调,所以造成页面不可见的情况下,音乐继续播放了10s

 

activity抢占后,为什么前一个activity的onstop延后那么长时间才回调呢?

经过系统分析,是主线程一直在忙,没有空闲下来,上一个activity一定要等待线程空闲下来,才会执行onstop。如果主线程一直没空闲下来,前一个acrivity岂不是一直没有机会执行回调onstop?android系统机制有这种容错机制,超过十秒没有回调,就会主动执行onstop。看到这种现象,跟这种机制基本吻合。看一下android源码,有一个IdleHandler,他是在主线程空闲的情况下执行。所以activyt抢占的情况,前一个activity的onstop就是在IdleHandler里处理的。主线程都是通过handler来处理消息,如果handler处理消息太多,就一直在工作状态,就一直没发执行IdleHandler里的消息。

 

问题定位:

知道问题的原因,分析代码,原来在第二个页面启动时候,会显示一个loadingview,这个loadingview会一直递归执行invalidate刷新view,造成主线程一直在工作状态,如果把刷新操作去掉,情况好很多,上一个activity的onstop基是是马上执行的。当时还有概率是10s后才执行。继续分析代码,播放器页面还有一个progressview,这个view跟loadingview是一样的处理方案,也是在onDraw里执行invalidate,把这个invalidate也注释调,这个问题就没有了。

 

解决方案:

activity的动画刷新频繁,就可能会造成IdleHandler没有被执行到,所以,我们的view在刷新的时候,不能在onDraw里执行invalidate,这样刷新太频繁了,我们可以使用handler,定期的刷新,1s或者几百毫秒刷新一次,这样就没有问题了。

 

总结:我遇到的问题,是因为在activity的onresume里,执行频繁执行view的刷新,造成主线程没有空闲状态。除了view的刷新,还有可能会有其他一些操作(如频繁发handler消息),可能会引起主线程的处于工作状态,而导致空闲状态要执行的操作没有得到及时的处理

参考:https://www.jianshu.com/p/479b78235361

 

另外推荐两篇博客,activity的启动过程分析

1、activity启动过程简单记录

https://www.jianshu.com/p/cbc7c61acbc0

2、activity生命周期流程简单记录

https://www.jianshu.com/p/b7919387b3a0