getApplication() vs. getApplicationContext()

我找不到一个令人满意的答案,所以我们开始:Activity/Service.getApplication()Context.getApplicationContext()是什么关系?

在我们的应用程序中,两者返回相同的对象。然而,在ActivityTestCase中,模拟应用程序将使getApplication()返回模拟,但getApplicationContext仍将返回一个不同的上下文实例(由Android注入)。那是虫子吗?是故意的吗?

我一开始都不明白有什么区别。在测试套件之外是否存在两个调用可能返回不同对象的情况?什么时候,为什么?此外,为什么getApplication定义在ActivityService上,而不是Context上?在任何地方中不应该总是有一个有效的应用程序实例可用吗?

338555 次浏览

比较getApplication()getApplicationContext()

getApplication返回一个Application对象,该对象允许你管理全局应用程序状态,并响应一些设备情况,如onLowMemory()onConfigurationChanged()

getApplicationContext返回全局应用程序上下文-与其他上下文的区别是,例如,当你的活动结束时,一个活动上下文可能被Android销毁(或以其他方式使不可用)。当你的应用程序对象存在时,应用程序上下文一直是可用的(它不绑定到特定的Activity),所以你可以使用它来处理像通知这样需要上下文的事情,这些上下文将会在更长的时间内可用,并且独立于临时UI对象。

我想这取决于你的代码在做什么——尽管在正常使用中,我希望它们是不同的。

要回答这个问题,getApplication()返回一个Application对象,getApplicationContext()返回一个Context对象。根据您自己的观察,我假设两者的上下文是相同的(即在幕后,应用程序类调用后一个函数来填充基类的上下文部分或进行一些等效的操作)。如果你只是需要一个Context,那么调用哪个函数并不重要。

非常有趣的问题。我认为这主要是语义上的意思,也可能是由于历史的原因。

虽然在当前的Android活动和服务实现中,getApplication()getApplicationContext()返回相同的对象,但不能保证总是如此(例如,在特定的供应商实现中)。

因此,如果你想要在Manifest中注册的Application类,你应该从来没有调用getApplicationContext()并将其转换为你的应用程序,因为它可能不是应用程序实例(这显然是你在测试框架中经历过的)。

为什么getApplicationContext()首先存在?

getApplication()只在Activity类和Service类中可用,而getApplicationContext()在Context类中声明。

这实际上意味着一件事:当在广播接收器中编写代码时,它不是一个上下文,但在其onReceive方法中提供了一个上下文,您只能调用getApplicationContext()。这也意味着您不能保证能够访问BroadcastReceiver中的应用程序。

当查看Android代码时,你会看到当附加时,一个活动接收一个基本上下文和一个应用程序,这是不同的参数。getApplicationContext()将它的调用委托给baseContext.getApplicationContext()

还有一件事:文档说在大多数情况下,你不需要子类化Application:

通常不需要子类化Application。在大多数情况下, 静态单例可以以更模块化的方式提供相同的功能 道路如果你的单例需要一个全局上下文(例如注册 广播接收器),检索它的函数可以给出一个 Context在内部使用Context.getApplicationContext()

我知道这不是一个确切的答案,但是,这是否回答了你的问题?

这似乎与上下文包装有关。大多数从Context派生的类实际上是ContextWrapper,它本质上委托给另一个上下文,可能由包装器更改。

上下文是支持模拟和代理的一般抽象。由于许多上下文都绑定到一个有限生命周期的对象,例如Activity,因此需要一种方法来获得一个更长的生命周期的上下文,例如为将来的通知注册。这是通过Context.getApplicationContext()实现的。逻辑实现是返回全局Application对象,但是没有什么可以阻止上下文实现返回具有合适生命期的包装器或代理。

活动和服务更具体地与Application对象相关联。我相信,这样做的有用之处在于,你可以创建并在清单中注册一个派生自Application的自定义类,并确保Activity.getApplication()Service.getApplication()将返回该特定类型的特定对象,你可以将其强制转换为派生的Application类并用于任何自定义目的。

换句话说,getApplication()保证返回一个Application对象,而getApplicationContext()可以自由返回一个代理。