android - onStop 在 onDestroy 之后被调用?
问题描述
我在Activity
生命周期中遇到了一个相当奇怪的问题。
短前传:
我发现的第一个症状是当我在注册接收器后IllegalArgumentException
尝试注销接收器时它崩溃了。onStop
onStart
在转储活动接收器的完整列表(一些反射魔法)之后,我发现我的接收器不在列表中。它要么是被错误地移到其他地方,要么是在onDestroy
调用正在清理的Activity
地方(在调用期间,然后调用)期间被删除。Context
onDestroy
ActivityThread
ContextImpl#performFinalCleanup
LoadedApk#removeContextRegistrations
怎么了?
在向崩溃添加更多分析信息后,我发现当崩溃发生时onStop
,Activity
它处于一个非常奇怪的状态 - 它是isDestroyed()
调用返回true
,它是isFinishing()
返回false
,它是getLifecycle().getCurrentState()
返回DESTROYED
......
检查正常onStop()
(没有崩溃)调用表明Activity
处于这种状态:
isDestroyed()
是false
,getLifecycle().getCurrentState()
并且CREATED
在onStop
。
所以我得出了onStop
被调用的结论onDestroy
,我认为这是不可能的,但它似乎发生了。
并且onStop
绝对不会被应用程序中的其他东西手动调用,因为这是调用的堆栈跟踪onStop
。
com.myapp.TheActivity.onStop (TheActivity.java:217)
android.app.Instrumentation.callActivityOnStop (Instrumentation.java:1474)
android.app.Activity.performStop (Activity.java:8189)
android.app.ActivityThread.callActivityOnStop (ActivityThread.java:4994)
android.app.ActivityThread.performStopActivityInner (ActivityThread.java:4967)
android.app.ActivityThread.handleStopActivity (ActivityThread.java:5047)
android.app.servertransaction.TransactionExecutor.performLifecycleSequence (TransactionExecutor.java:233)
android.app.servertransaction.TransactionExecutor.cycleToPath (TransactionExecutor.java:201)
android.app.servertransaction.TransactionExecutor.executeLifecycleState (TransactionExecutor.java:173)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2220)
android.os.Handler.dispatchMessage (Handler.java:107)
android.os.Looper.loop (Looper.java:237)
android.app.ActivityThread.main (ActivityThread.java:8016)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1076)
解决方案
原因尚不清楚,但最近越来越受到关注。它发生在 onResume/onPause 和 onStart/onStop 对中调用注册/取消注册。关于这些生命周期检查,请确保您拥有带有 hashCode() 或其他东西的活动实例。无论如何,要解决此问题,最佳做法是将注册/取消注册调用包装在 try/catch 块中:
private void registerBroadcastReceiver() {
try {
appUpdateReceiver = new AppUpdateReceiver();
registerReceiver(appUpdateReceiver, appUpdateIntentFilter);
} catch (IllegalArgumentException e) {
// already registered
}
}
private void unregisterBroadcastReceiver() {
try {
unregisterReceiver(appUpdateReceiver);
} catch (IllegalArgumentException e) {
// already unregistered
}
}
推荐阅读
- java - 如何从 Angular 应用程序打开桌面应用程序?
- swift - 将object3d放在海拔位置目标位置
- python - 如何将熊猫数据框从 praw 保存到 xlsx?
- reactjs - ReactJS 中的里程表
- xml - 如何在模板内添加新模板?
- amazon-web-services - Alexa 触发器可以将变量发送到 Lambda
- azure - 通过数组运行的 Azure 模板
- java - Hibernate:冗长的 ArrayLists 的持久性优化
- javascript - 如何使用 javascript 从 JSON 文件创建网格
- jenkins-pipeline - Jenkins 声明性管道发布总是条件在日志中引发错误