如何修复 onDestroy 的“SuperNotCalledException”?

How to fix 'SuperNotCalledException" of onDestroy?

我在片段内使用 onDestroy 以确保在退出应用程序时停止处理程序(用于为按钮设置动画),如下面的代码所示:

@Override
public void onDestroy () {
    if (anim1 !=null && run1 !=null) {
        anim1.removeCallbacks(run1);
    }
    super.onDestroy ();
}

anim1是Handler; run1 是 Runnable。

代码 在我的测试设备中按预期工作(运行 各种 Android 版本,但不是 6.0 或 8.1 - 这将是一个问题,如您所见)。根据 Google 控制台报告和一般反馈判断,它也适用于绝大多数用户。

换句话说,如果用户在 Handler/Runnable 仍然存在的情况下尝试离开应用程序(或移动到另一个片段),则不会抛出异常并且 anim1.removeCallbacks(run1); 被触发为预期没有错误。

查看来自 Google 控制台的报告,但是,一些 Android 6.0 和 8.1 用户遇到了 SuperNotCalledException(下面提供的日志)。从数字上看,与 6.0

相比,8.1 用户似乎受到的影响更大

我知道问题出在我的 onDestroy 实现中,因为这个错误 (SuperNotCalledException) 开始出现在 Google 控制台上 我实现上面的代码之后。在我获得 NPE 之前,由于应用程序退出时处理程序仍然 运行 (此错误不再存在)。

我只收到一些错误报告,所以显然它只影响少数用户。但我想知道我做错了什么以及如何解决它。

我已经看过其他类似的问题,例如:

Fatal error: supernotcalledexception

NullPointer at OnDestroy

但它们似乎与我的问题无关。 super.onDestroy 在我的代码里,它在最后。 logcat 也不太暴露(至少对我而言):

Huawei Honor 7A (HWDUA-M), Android 8.1
Report 1 of 1
java.lang.RuntimeException: 
  at android.app.ActivityThread.performDestroyActivity (ActivityThread.java:4679)
  at android.app.ActivityThread.handleDestroyActivity (ActivityThread.java:4697)
  at android.app.ActivityThread.-wrap5 (Unknown Source)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1837)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loop (Looper.java:166)
  at android.app.ActivityThread.main (ActivityThread.java:6861)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:450)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:936)
Caused by: android.support.v4.app.SuperNotCalledException: 
  at android.support.v4.app.Fragment.performDestroy (Fragment.java:2590)
  at android.support.v4.app.FragmentManagerImpl.moveToState (FragmentManager.java:1566)
  at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState (FragmentManager.java:1759)
  at android.support.v4.app.FragmentManagerImpl.moveToState (FragmentManager.java:1836)
  at android.support.v4.app.FragmentManagerImpl.dispatchStateChange (FragmentManager.java:3244)
  at android.support.v4.app.FragmentManagerImpl.dispatchDestroy (FragmentManager.java:3235)
  at android.support.v4.app.FragmentController.dispatchDestroy (FragmentController.java:265)
  at android.support.v4.app.FragmentActivity.onDestroy (FragmentActivity.java:390)
  at android.support.v7.app.AppCompatActivity.onDestroy (AppCompatActivity.java:209)
  at android.app.Activity.performDestroy (Activity.java:7335)
  at android.app.Instrumentation.callActivityOnDestroy (Instrumentation.java:1249)
  at android.app.ActivityThread.performDestroyActivity (ActivityThread.java:4666)

知道我可以尝试进一步解决问题吗?我觉得有点莫名其妙,因为实际上是 3 行代码导致了问题,而且我不知道如何将它们组合在一起。

如果您需要任何进一步的详细信息或代码,请告诉我,我们很乐意提供。

我将添加我的解决方案作为答案,以防其他人发现它有用。 事实证明,问题不在 这个特定的 片段和代码中,而是在另一个类似的片段中。

我有 copied/pasted 所有这些代码,但在某个时候,某个地方,我发现搜索的代码是这样的:

@Override
public void onDestroy () {
    if (anim1 !=null && run1 !=null) {
    anim1.removeCallbacks(run1);
    super.onDestroy ();
    }
}

由于 super.onDestroy () 不小心落入了 if-statement,因此每当 activity 在 anim1 and/or run1 期间被摧毁时,它就无法到达为空。由于 logcat 没有报告发生异常的 哪个 片段,因此检测它并没有变得更容易。

这个故事的寓意是,始终检查代码的所有实例,即使您有 copied/pasted 它也是如此。