公共(public)类 MyApplication extends Application 引起的 java.lang.NullPointerException

标签 java android nullpointerexception singleton extends

在检查我的 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 中解释的。 :

However, you should never store mutable instance data inside the Application object because if you assume that your data will stay there, your application will inevitably crash at some point with a NullPointerException. The application object is not guaranteed to stay in memory forever, it will get killed. Contrary to popular belief, the app won’t be restarted from scratch. Android will create a new Application object and start the activity where the user was before to give the illusion that the application was never killed in the first place.

我尝试使用这个进行日志记录:

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 已经失去了它的值(value),然后我得到了 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.
        .....
    }
}

最佳答案

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

The OS may kill processes as necessary. All processes are divided into 5 levels of "killability" specified in the documentation.

So, for instance, if your app goes in the background due to the user answering to an incoming call, then depending on the state of the RAM, the OS may (or may not) kill your process (destroying the Application instance in the process).

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

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

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

关于公共(public)类 MyApplication extends Application 引起的 java.lang.NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57615269/

相关文章:

java - Maven 为我创建的没有依赖项的 jar 有什么用?

java - 更改现有 PDF 文档的方向(纵向/横向)

java - Spring 4 和 Java 8 无效字节标记异常

android - 如何为包含&的谷歌地图形成一个网址

java - 您如何找到空指针异常的确切变量?

hibernate - Grails createCriteria返回空条件

javafx 在 Netbeans IDE 之外运行应用程序

java - 如何指示 ArrayAdapter 重绘其所有元素?

java - 使用 values.xml 设置 Android Activity 屏幕方向

Java 在类空间中实例化类数组会产生 NullPointerException