1. 背景
最近工作中碰到一个奇怪的bug,原因是因为activity的onStart和onStop生命周期函数没有按照期望的方式被调用。从我们的activity跳转到一个第三方activity后,我们的activity的onStop居然没有被调用;从第三方activity回到我们的activity的时候,我们的activity的onStart也没有被调用。头一次碰到这样的问题,百思不得其解。
先看看官方的activity生命周期示意图:
我们理解的没错啊,比如说有A和B两个全屏的activity,从A跳转到B,正常情况应该是会调用A的onPause和onStop,会调用B的onStart和onResume;然后从B回到A,正常情况应该是会调用B的onPause和onStop,会调用A的onStart和onResume。这里先忽略跟我们这个问题无关的生命周期函数。是什么原因导致了这个问题呢?
2. 原因分析
要搞清楚这个问题的原因,我们需要知道onStart和onStop什么时候会被系统回调,这里以onStop为例进行说明。还是拿上边的例子进行说明,从A activity跳到B activity时,最终会调用下边这个方法来判断stack里的各个activity的可见性。
这个方法依赖下边的两个核心方法
如果表示B activity的ActivityRecord.fullscreen的值为false,那什系统就会认为B activity不是全屏的,从而判断A activity依然还是可见的。跳到B activity后就不会调用A activity的onStop函数。系统是怎么给ActivityRecord.fullscreen这个属性赋值的呢?换言之就是系统是怎么判断一个activity是全屏还是非全屏呢?在启动B activity的过程中,系统会创建一个ActivityRecord这样的对象来表示一个activity,ActivityRecord的构造函数如下:
3. 结论
至此就真相大白了,如果一个activity的属性的windowIsTranslucent被设置为true或者windowSwipeToDismiss被设置为true或者windowIsFloating被设置为true,那个这个activity就会被系统认为是非全屏的。因为系统认为你要跳转的activity是非全屏的,自然也就不会调用前一个activity的onStop函数,因为没有调用onStop,回到前一个activity的时候自然也不会调用onStart。
4. 解决方案
在给activity设置windowIsTranslucent或者windowIsFloating样式的时候,需要谨慎,确保你真的activity真的需要这两个属性。如果某个activity确实需要设置windowIsTranslucent或者windowIsFloating属性,那就要做好前一个activity的onStart和onStop不会被调用的准备,如果又有需要依赖这两个生命周期函数的逻辑,可以考虑使用onResume和onPause替代。