443

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

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

我什至不明白首先有什么区别。在测试套件之外是否存在两个调用可能返回不同对象的情况?什么时候,为什么?此外,为什么在and上getApplication定义,而不是在 上?不应该总是有一个有效的应用程序实例可以从任何地方获得吗?ActivityServiceContext

4

4 回答 4

386

非常有趣的问题。我觉得主要是语义,也可能是历史原因。

尽管在当前的 Android Activity 和 Service 实现中,getApplication()getApplicationContext()返回相同的对象,但不能保证总是如此(例如,在特定的供应商实现中)。

所以如果你想要你在 Manifest 中注册的 Application 类,你永远不应该调用getApplicationContext()它并将其转换为你的应用程序,因为它可能不是应用程序实例(你显然在测试框架中体验过)。

为什么getApplicationContext()首先存在?

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

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

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

还有一件事:文档说在大多数情况下,您不需要子类化应用程序:

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

我知道这不是一个准确而准确的答案,但是,这能回答你的问题吗?

于 2011-07-20T09:52:19.167 回答
33

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

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

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

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

于 2012-11-01T00:26:53.340 回答
29

比较getApplication()getApplicationContext()

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

getApplicationContext返回全局应用程序上下文 - 与其他上下文的区别在于,例如,活动上下文可能会在您的活动结束时被 Android 销毁(或以其他方式变为不可用)。Application 上下文在您的 Application 对象存在时始终保持可用(它不绑定到特定的Activity),因此您可以将其用于通知之类的事情,这些事情需要在较长时间内可用且独立于瞬态 UI 对象的上下文。

我想这取决于您的代码在做什么,它们是否相同 - 尽管在正常使用中,我希望它们会有所不同。

于 2011-02-16T16:47:53.373 回答
-13

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

于 2011-05-04T19:22:35.783 回答