在Android开发中,Activity跳转的生命周期,我们都再熟悉不过了,但是有一些特别的应用场景,生命周期方法却会出现一些我们意料外的调用顺序。
正常的Activity跳转生命周期
从 main 创建,到启动新的页面second,正常的生命周期是这样的:
main onCreate // --------
main onStart // |
main onResume // |
main onPause // |
second onCreate // | main atartActivity second
second onStart // |
second onResume // v
main onStop // --------
second Activity调用finish()回到main,正常的生命周期是这样的:
second onPause // --------
main onStart // |
main onResume // | second finish() to main
second onStop // v
second onDestroy // --------
一些异常情况
但我在开发中,在接入一家第三方厂商的aar形式的SDK时,却遇到了一种特别的情况,上面描述的 main -> second -> main
过程生命周期变成了下面这样:
main onCreate // --------
main onStart // |
main onResume // |
main onPause // |
second onCreate // | main atartActivity second
second onStart // |
second onResume // v
main onStop // --------
second onPause // --------
main onDestroy // |
main onCreate // |
main onStart // |
main onResume // |
main onPause // |
// 1 // | second finish() to main
main onResume // |
second onStop // v
second onDestroy // --------
甚至,在上边注释1的位置,log中还抛出了一个运行时异常:Performing pause of activity that is not resumed
:
E/ActivityThread: Performing pause of activity that is not resumed: {com.xxx.xx.xx/com.xx.xx.MainActivity}
java.lang.RuntimeException: Performing pause of activity that is not resumed: {com.xxx.xx.xx/com.xx.xx.MainActivity}
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:5176)
at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:5129)
at android.app.servertransaction.PauseActivityItem.execute(PauseActivityItem.java:46)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:190)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:105)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2473)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8349)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
我这里的情况,经过一番排查,发现是屏幕方向发生改变引起的。在这个问题场景中,main的方向是portrait
,second的方向是landscape
。然后在second调用finish()
返回main时,就先destroy了,并且还出现了两次resume的奇怪顺序。
解决的方法,自然就是给main页面加上configChanges
选项。
<activity android:name=".MainActivity"
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation|screenSize">
找到原因后发现其实是很基础很简单的问题,但在复杂工程中出现,还是花了一些时间排查。