似乎在应用程序对象之前创建了Activity

问题描述 投票:2回答:3

我一直在Play商店收到一些崩溃报告,这对我来说似乎很疯狂。由于NullPointerException,一些活动(在1种情况下,它是广播接收器)在onCreate()/ onResume()中崩溃。

这些活动使用静态方法,而静态方法又使用Application singleton [for context],但返回的对象为null,就像应用程序对象根本不存在一样。根据我的理解,应用程序应该始终有一个实例。

我的代码是普通的,应用程序在其onCreate()中设置静态字段,活动调用的类使用返回应用程序对象的MyApplication.getInstance()。

从活动调用时,MyApplication.getInstance()如何返回null?我不知道怎么会发生这种情况。

当然,我无法复制这次崩溃。这主要发生在Android 6中,但我有一些来自Android 8和9的报告。

android crash android-lifecycle application-lifecycle
3个回答
2
投票

我想你正在做这个question中投票最多的回答。但是,您应该看到许多人在评论中警告的内容:

缺点是在某些静态初始化代码尝试获取Context对象之前,无法保证会调用非静态onCreate()。这意味着你的调用代码需要准备好处理空值,这有点打败了这个问题的全部要点。 - 梅琳达格林

.

令人沮丧的是看到这个答案有多少赞成。你永远不应该将静态实例保存到上下文中 - 为了证明,尝试使用泄漏金丝雀(github.com/square/leakcanary)并找到由此引起的内存泄漏。 @ people-with-enouhg-rep-and-Android-knowledge,请重新审核此答案并采取相应措施。保证初学者可以使用它,这很简单。 - Crearo Rotar

你应该:

  • 尽可能使用您的Activity上下文并将其传递给任何其他需要它的类。
  • 或者,我真正推荐的是,使用Dagger2设置依赖注入。一开始学习有点困难,但有很多信息和教程可以帮助您入门。正确设置Dagger之后,您需要以空安全的方式访问应用程序上下文,只需在相应的类中注入它,如下所示: public class MyClass { @Inject Context context; ... }

0
投票

作为关于匕首依赖注入的另一个答案的替代方案,我只想举例说明以旧式方式从活动中获取上下文。如果将上下文声明为成员变量,它将在您的活动中可用,并且可以根据需要传递给其他类:

public class ExampleActivity extends AppCompatActivity {

    private Context mContext;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);
        mContext = this;
    }

0
投票

我想我找到了原因。在Android 6自动恢复未初始化应用程序时,问题是相同的,他们将原因确定为Android 6中引入的自动备份功能。基本上,从备份恢复后,应用程序以奇怪的方式重新启动在Activity之前不创建Application对象。我们现在可以重现问题,禁用备份可以解决问题。

© www.soinside.com 2019 - 2024. All rights reserved.