Activity 似乎是在应用程序对象之前创建的
Posted
技术标签:
【中文标题】Activity 似乎是在应用程序对象之前创建的【英文标题】:Activity seems to be created before application object 【发布时间】:2019-04-09 17:09:43 【问题描述】:我在 Play 商店中收到了一些崩溃报告,起初我觉得这很疯狂。 由于 NullPointerException,某些活动(在 1 种情况下是广播接收器)在 onCreate()/onResume() 中崩溃。
这些活动使用静态方法,而这些方法又使用 Application 单例 [for context],但返回的对象为 null,就像应用程序对象根本不存在一样。据我了解,应用程序应该始终有一个实例。
我的代码很普通,应用在其onCreate()中设置了一个静态字段,Activity调用的类使用MyApplication.getInstance()返回应用对象。
MyApplication.getInstance() 从活动调用时如何返回 null?我不知道这是怎么发生的。
当然,我无法复制这次崩溃。 这主要发生在 android 6 中,但我有一些来自 Android 8 和 9 的报告。
【问题讨论】:
为什么需要应用上下文?您可以改用您的活动的上下文吗?取决于应用程序上下文通常不是您想要做的事情。 【参考方案1】:我猜你正在做这个question 中投票最多的答案。 但是,您应该看到许多人在 cmets 中警告的内容:
缺点是不能保证非静态 onCreate() 将在一些静态初始化之前被调用 代码尝试获取您的 Context 对象。 这意味着您的调用代码 需要准备好处理失败的空值 这个问题的重点。 – 梅琳达格林
.
看到这个答案有多少赞成票,真是令人沮丧。 Y你永远不应该将静态实例保存到上下文中——为了证明,尝试使用 Leak Canary (github.com/square/leakcanary) 并找出由此引起的内存泄漏。 @people-with-enouhg-rep-and-Android-knowledge,请重新查看此答案并采取相应措施。保证初学者可以使用它,这是很简单的错误。 – Crearo Rotar
您应该:
尽可能使用您的 Activity 上下文并将其传递给需要它的任何其他类。或者,我真正推荐的是,使用Dagger2 设置依赖注入。刚开始学习有点困难,但是有很多信息和教程可以帮助您入门。正确设置 Dagger 后,您需要以 null 安全的方式访问应用程序上下文,只需将其注入相应的类中,如下所示:
public class MyClass
@Inject
Context context;
...
【讨论】:
【参考方案2】:作为关于 dagger 依赖注入的其他答案的替代方案,我只是想举一个例子,以老式的方式从活动中获取上下文。如果您将 context 声明为成员变量,它将在您的整个活动中可用,并且可以根据需要传递给其他类:
public class ExampleActivity extends AppCompatActivity
private Context mContext;
@Override protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
mContext = this;
【讨论】:
【参考方案3】:我想我找到了原因。在 Android 6 自动恢复未初始化应用程序中,问题是相同的,他们确定原因是 Android 6 中引入的自动备份功能。基本上,从备份恢复后,应用程序以一种奇怪的方式重新启动,其中Application 对象不是在 Activity 之前创建的。我们现在可以重现问题并禁用备份解决问题。
【讨论】:
以上是关于Activity 似乎是在应用程序对象之前创建的的主要内容,如果未能解决你的问题,请参考以下文章
错误的窗口令牌,您无法在创建 Activity 之前或隐藏之后显示对话框
从 Activity 导航到 Fragment 并返回到 Activity 导致该 Activity 被多次创建