【问题标题】:java.lang.NullPointerException caused by public class MyApplication extends Application由公共类 MyApplication 扩展 Application 引起的 java.lang.NullPointerException
【发布时间】:2019-08-22 18:32:36
【问题描述】:

在检查我的 Android 应用程序崩溃报告时,我注意到 java.lang.NullPointerException 是导致崩溃的主要原因之一。这是我经常崩溃的一个例子:

    java.lang.RuntimeException:
      at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3364)
      at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3548)
      at android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:86)
      at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:108)
      at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:68)
      at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2155)
      at android.os.Handler.dispatchMessage (Handler.java:109)
      at android.os.Looper.loop (Looper.java:207)
      at android.app.ActivityThread.main (ActivityThread.java:7539)
      at java.lang.reflect.Method.invoke (Native Method)
      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:524)
      at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:958)
    Caused by: java.lang.NullPointerException:
      at com.myapp.ProductDetails.onCreate (ProductDetails.java:47)
      at android.app.Activity.performCreate (Activity.java:7441)
      at android.app.Activity.performCreate (Activity.java:7431)
      at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1286)
      at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3343)

我去检查了我在com.myapp.ProductDetails.onCreate (ProductDetails.java:47) 中的内容,结果是这样的:

ProductDetail productDetail = MyApplication.getInstance().pDetail;

我知道该行导致了java.lang.NullPointerException 并因此导致崩溃。问题是为什么?我正在使用Application,这是https://developer.android.com/reference/android/app/Application 中解释的用于维护全局应用程序状态的基类。我正在继承应用程序:

import android.app.Application;
.....
public class MyApplication extends Application{
    static MyApplication _instance;
    public ProductDetail pDetail;
    .....
    @Override
    public void onCreate() {
        super.onCreate();
        _instance= this;
        .....
    }
    .....
    public static MyApplication getInstance(){
        return _instance;
    }
}

但是当我使用ProductDetail productDetail = MyApplication.getInstance().pDetail; 时,有时我会得到java.lang.NullPointerException。我要强调的是,这条线有时会导致java.lang.NullPointerException,而不是一直。我的理论是,我的应用程序发生的事情是 https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class 解释的:

但是,您永远不应该将可变实例数据存储在 Application 对象,因为如果您假设您的数据将保留 在那里,您的应用程序将不可避免地在某个时候崩溃 NullPointerException。申请对象不保证留下 永远在记忆中,它会被杀死。与流行的看法相反, 应用程序不会从头开始重新启动。 Android将创建一个新的 Application 对象并启动用户之前的活动 给人一种应用程序一开始就没有被杀死的错觉 地点。

我尝试使用此日志记录:

ACRA.getErrorReporter().putCustomData("ACRA CUSTOM_DATA begins","ACRA CUSTOM_DATA begins");ACRA.getErrorReporter().putCustomData("MyApplication.getInstance()", MyApplication.getInstance().toString());ACRA.getErrorReporter().putCustomData("MyApplication.getInstance().pDetail", MyApplication.getInstance().pDetail.toString());ProductDetail productDetail = MyApplication.getInstance().pDetail;ACRA.getErrorReporter().putCustomData("ACRA CUSTOM_DATA ends","ACRA CUSTOM_DATA ends");

在日志结果中,我只看到这个:

CUSTOM_DATA=ACRA CUSTOM_DATA begins = ACRA CUSTOM_DATA begins
MyApplication.getInstance() = com.myapp.MyApplication@c190fea

我解释它的方式是MyApplication.getInstance().toString() 不会使应用程序崩溃,因为即使原始的MyApplication 丢失了(这是我的假设,如果进程在某个时候被杀死,那么该对象可能会丢失) 因为MyApplication.getInstance().toString() 创建了一个新对象,因为原始对象丢失了(我的假设)。但是当我尝试执行MyApplication.getInstance().pDetail.toString() 时,应用程序确实崩溃了,因为它已经丢失了成员变量pDetail 的值,因为MyApplication 将持有一个新对象,而不是原来的具有值的对象MyApplication.getInstance().pDetail 正确分配。所以我的解释是,即使我希望MyApplication.getInstance() 始终持有一个且只有一个对象,并且一直保持相同,直到我明确关闭应用程序,也许MyApplication 对象会丢失,然后使用MyApplication.getInstance() 创建一个新的目的。那么java.lang.NullPointerException 就有意义了。两个问题。 1. 你觉得这个解释合理吗?如果不是,为什么? 2. 你会建议做什么来重写我的代码,以便我修复这个我偶尔得到的java.lang.NullPointerException?有趣的是,当我长时间最小化应用程序(例如几小时或几天)然后重新打开它时,我已经看到这种情况发生在我身上。这是有道理的,因为也许进程被杀死了,当我将最小化的应用程序带回前台时,MyApplication.getInstance() 可能正在创建全新的进程或对象,而不是已经创建的原始进程或对象,因此,MyApplication.getInstance().pDetail本来已经失去了它的价值,然后我得到了java.lang.NullPointerException。这个理论有意义吗?

更新 1:

ProductDetail 是我拥有的一个类,其中包含导致崩溃的行和java.lang.NullPointerException:

public class ProductDetail extends FragmentActivity implements OnMapReadyCallback {
    .....
    static ProductDetail _instance;
    protected void onCreate(Bundle savedInstanceState) {
        .....
        ProductDetail productDetail = MyApplication.getInstance().pDetail; // This is the line that SOMETIMES causes the app to crash with a java.lang.NullPointerException.
        .....
    }
}

【问题讨论】:

  • 你的ProductDetail 班级是什么?
  • @GauravMall 见我的UPDATE 1
  • 嗯,你定义过pDetail吗?
  • 另外,您是否在清单中声明了您的MyApplication 类?
  • 太好了,知道你在找什么。等一下

标签: java android nullpointerexception singleton extends


【解决方案1】:

嗯,是的,您认为应用程序实例可以被杀死的假设是正确的。您有时发生的错误就是证明。正如这篇文章所说:

操作系统可能会根据需要终止进程。所有进程分为documentation中指定的5个“可杀性”级别。

因此,例如,如果您的应用由于用户接听来电而进入后台,那么根据 RAM 的状态,操作系统可能(也可能不会)终止您的进程(破坏应用程序实例过程中)。

您的应用程序实例作为存储类用例并不可靠。例如,让我们举个例子:

  • 您的应用进入后台,因为您的用户已进入主应用抽屉,或者您的应用正在消耗不必要的内存或电池。
  • 文档说因为您的应用在后台运行您的服务,或者有时应用状态为“已取消”。

这就是为什么您没有看到那么多在应用程序实例中存储数据的方法。大多数时候,您会使用SharedPreferences,或者将其写入本地文本、自定义文件。本文包含更多信息:Using the Android Application class to persist data

【讨论】:

  • 是否有关于何时何地杀死事物的顺序?应用程序会是第一个还是它是如何工作的?
  • 是的,有。 Android 将每个服务都赋予了重要性级别。一旦某件事变得不重要,android就会杀死它。查看文档:developer.android.com/guide/components/activities/…
【解决方案2】:

http://www.developerphil.com/dont-store-data-in-the-application-object/ 对根本原因进行了很好的解释。这是根据那篇文章的解决方案:

这里没有神奇的解决方案,您可以执行以下操作之一:

  1. 通过 Intent 显式地将数据传递给 Activity。
  2. 使用多种方法之一将数据持久保存到磁盘。
  3. 始终进行空值检查并手动处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    相关资源
    最近更新 更多