Gingerbread和ICS之间SQLite数据库生命周期的变化;间歇性空指针异常

时间:2012-07-03 20:37:37

标签: android sqlite nullpointerexception lifecycle onresume

我注意到,当我从Gingerbread升级到ICS后,我的应用程序开始崩溃,因为它在Gingerbread下令人满意地工作。

应用程序的主要活动(活动A)有一个菜单选项,用于打开从数据库填充的ListActivity(活动B);单击列表中的条目时,将打开第三个活动(活动C)。当使用后退按钮关闭活动C时,应该重新显示活动B.

在Gingerbread(以及早期的Android版本)中,这种方法运行良好,并且大部分时间都在ICS中继续正常工作。但是,如果我离开应用程序离开活动C一段时间,它就会崩溃。在返回应用程序并尝试将活动C退出到活动B时,应用程序将停止。 LogCat报告“无法恢复活动”,因为活动B中的onResume中存在空指针异常。

onResume方法中的违规行包含对DBAdapter的引用,该引用在活动A的onCreate方法中定义。通过记录对活动B的各种生命周期方法的调用,我发现活动B始终(如预期的那样)在活动时停止C打开了。只要它停止就没有问题:调用onResume时仍必须定义DBAdapter。但是,如果应用程序停留较长时间,活动B将被销毁,在这种情况下,DBAdapter(在活动A的onCreate方法中定义)也必须变为未定义。

此问题的解决方法似乎是将if (Global.mDBAdapter== null) {Global.mDBAdapter = new DBAdapter( this, "DatabaseName" );}插入到活动B的onCreate方法中。

我想检查一下我是否正确理解了这一点。是否有文档描述了SQLite数据库适配器/帮助程序的生命周期行为中的变化(Gingerbread和ICS之间)?

1 个答案:

答案 0 :(得分:1)

看起来你做的假设是不合理的,而你恰巧在你的Gingerbread设备上躲过它们。

在调用onStop()后的任何时候,活动的进程始终处于可填充状态,因此在onStop()结束时,您必须为下一个生命周期回调做好准备,使其成为这三个中的任何一个:

  1. onRestart() - 如果没有杀死进程并且不久重新启动Activity。
  2. onDestroy() - 如果系统决定停止活动,并且发现方便通知您。
  3. onCreate() - 如果该进程在未调用onDestroy()的情况下被杀死。
  4. (Pre-Honeycomb,在onPause()之后,该过程甚至可以暂停。)

    所以听起来就是这样,当你长时间离开活动C时,整个过程就会被杀死。当您返回活动C,然后按BACK,活动B通过onCreate() - > onStart() - > onResume(),您似乎假设您已经通过活动A设置了全局状态,但事实并非如此。

    这不是Gingerbread和ICS之间的变化;你之前很幸运。

    阅读和理解的良好资源:

    更新:您在下面的评论中询问了Android在销毁应用程序时的状态。我的印象是它基本上只是活动堆栈和来自onSaveInstanceState()的任何捆绑包。 (它没有特别记住哪个Activity是开放的,这只是堆栈的顶部。)这是有道理的:Android处理其结束(活动堆栈)并处理你的(通过保存最重要的东西并准备好重新创造其余部分。)

    onSaveInstanceState()的默认实现会在您的所有视图上调用相同名称的方法,这可能会让您看起来像是免费保存和恢复了一些数据。但是,如果不重写该方法,您肯定不会保存您自己的任何数据成员,静态或其他方式。这对我来说很有意义:自动这样做需要反思,效率低下,经常浪费,而且相当混乱。由您来保存重要的保存内容,Android会为您提供回调以使其变得简单。

    这是您的另一个资源:

    但是,您不一定需要处理onSaveInstanceState();有些事情比重新创建更有意义,例如你的数据库适配器。