我找不到令人满意的答案,所以我们开始:Activity/Service.getApplication()
和 Context.getApplicationContext()
有何关系?
在我们的应用程序中,两者都返回相同的对象。然而,在 ActivityTestCase
中,模拟应用程序将使 getApplication()
返回模拟,但 getApplicationContext
仍将返回不同的上下文实例(由 Android 注入)。这是一个错误吗?是故意的吗?
我什至一开始就不明白其中的区别。在测试套件之外是否存在两个调用可能返回不同对象的情况?什么时候以及为什么?而且,为什么getApplication
定义在Activity
和Service
上,而不是定义在Context
上?难道不应该总是有一个可以从任何地方获得的有效应用程序实例吗?
I couldn't find a satisfying answer to this, so here we go: what's the deal with Activity/Service.getApplication()
and Context.getApplicationContext()
?
In our application, both return the same object. In an ActivityTestCase
however, mocking the application will make getApplication()
come back with the mock, but getApplicationContext
will still return a different context instance (one injected by Android). Is that a bug? Is it on purpose?
I don't even understand the difference in the first place. Are there cases outside a test suite where both calls may come back with different objects? When and why? Moreover, why is getApplication
defined on Activity
and Service
, but not on Context
? Shouldn't there always be a valid application instance available from anywhere?
发布评论
评论(4)
非常有趣的问题。我觉得主要是语义上的,也可能是历史原因造成的。
尽管在当前的 Android Activity 和 Service 实现中,
getApplication()
和getApplicationContext()
返回相同的对象,但不能保证情况总是如此(例如,在特定供应商实现中)。因此,如果您想要在清单中注册的 Application 类,您应该永远调用
getApplicationContext()
并将其转换为您的应用程序,因为它可能不是应用程序实例(您显然在测试框架中经历过)。为什么
getApplicationContext()
存在?getApplication()
仅在 Activity 类和 Service 类中可用,而getApplicationContext()
在 Context 类中声明。这实际上意味着一件事:在广播接收器中编写代码时,广播接收器不是上下文,但在其 onReceive 方法中给出了上下文,您只能调用 getApplicationContext() 。这也意味着不能保证您能够访问 BroadcastReceiver 中的应用程序。
查看 Android 代码时,您会发现附加时,活动会接收基本上下文和应用程序,而这些是不同的参数。
getApplicationContext()
将其调用委托给baseContext.getApplicationContext()
。另一件事:文档说,在大多数情况下,您不需要子类化应用程序:
我知道这不是一个准确的答案,但这仍然可以回答您的问题吗?
Very interesting question. I think it's mainly a semantic meaning, and may also be due to historical reasons.
Although in current Android Activity and Service implementations,
getApplication()
andgetApplicationContext()
return the same object, there is no guarantee that this will always be the case (for example, in a specific vendor implementation).So if you want the Application class you registered in the Manifest, you should never call
getApplicationContext()
and cast it to your application, because it may not be the application instance (which you obviously experienced with the test framework).Why does
getApplicationContext()
exist in the first place ?getApplication()
is only available in the Activity class and the Service class, whereasgetApplicationContext()
is declared in the Context class.That actually means one thing : when writing code in a broadcast receiver, which is not a context but is given a context in its onReceive method, you can only call
getApplicationContext()
. Which also means that you are not guaranteed to have access to your application in a BroadcastReceiver.When looking at the Android code, you see that when attached, an activity receives a base context and an application, and those are different parameters.
getApplicationContext()
delegates it's call tobaseContext.getApplicationContext()
.One more thing : the documentation says that it most cases, you shouldn't need to subclass Application:
I know this is not an exact and precise answer, but still, does that answer your question?
这似乎与上下文包装有关。大多数从
Context
派生的类实际上是ContextWrapper
,它本质上委托给另一个上下文,可能会由包装器进行更改。上下文是支持模拟和代理的通用抽象。由于许多上下文都绑定到有限生命周期的对象,例如
Activity
,需要有一种方法来获得更长久的上下文,用于注册未来通知等目的。这是通过Context.getApplicationContext()
。逻辑实现是返回全局Application
对象,但什么也没有防止上下文实现返回具有合适生命周期的包装器或代理。活动和服务更具体地与
Application
对象相关联。我相信,这样做的用处在于,您可以在清单中创建并注册从Application
派生的自定义类,并确保Activity.getApplication()
或Service.getApplication()
将返回该特定类型的特定对象,您可以将其转换为派生的 < code>Application 类并用于任何自定义目的。换句话说,
getApplication()
保证返回一个Application
对象,而getApplicationContext()
则可以自由地返回一个代理。It seems to have to do with context wrapping. Most classes derived from
Context
are actually aContextWrapper
, which essentially delegates to another context, possibly with changes by the wrapper.The context is a general abstraction that supports mocking and proxying. Since many contexts are bound to a limited-lifetime object such as an
Activity
, there needs to be a way to get a longer-lived context, for purposes such as registering for future notifications. That is achieved byContext.getApplicationContext()
. A logical implementation is to return the globalApplication
object, but nothing prevents a context implementation from returning a wrapper or proxy with a suitable lifetime instead.Activities and services are more specifically associated with an
Application
object. The usefulness of this, I believe, is that you can create and register in the manifest a custom class derived fromApplication
and be certain thatActivity.getApplication()
orService.getApplication()
will return that specific object of that specific type, which you can cast to your derivedApplication
class and use for whatever custom purpose.In other words,
getApplication()
is guaranteed to return anApplication
object, whilegetApplicationContext()
is free to return a proxy instead.比较
getApplication()
和getApplicationContext()
。getApplication
返回一个Application
< /a> 对象,它允许您管理全局应用程序状态并响应某些设备情况,例如onLowMemory()
和onConfigurationChanged()
。getApplicationContext
返回全局应用程序上下文 - 与其他上下文的区别在于,例如,当您的 Activity 结束时,Android 可能会销毁 Activity 上下文(或以其他方式使其不可用)。当您的应用程序对象存在时,应用程序上下文始终可用(不绑定到特定的Activity
),因此您可以将其用于通知,需要一个可长时间使用且独立于瞬态 UI 对象的上下文。我想这取决于你的代码在做什么,这些是否相同 - 尽管在正常使用中,我希望它们是不同的。
Compare
getApplication()
andgetApplicationContext()
.getApplication
returns anApplication
object which will allow you to manage your global application state and respond to some device situations such asonLowMemory()
andonConfigurationChanged()
.getApplicationContext
returns the global application context - the difference from other contexts is that for example, an activity context may be destroyed (or otherwise made unavailable) by Android when your activity ends. The Application context remains available all the while your Application object exists (which is not tied to a specificActivity
) so you can use this for things like Notifications that require a context that will be available for longer periods and independent of transient UI objects.I guess it depends on what your code is doing whether these may or may not be the same - though in normal use, I'd expect them to be different.
为了回答这个问题,getApplication() 返回一个 Application 对象,而 getApplicationContext() 返回一个 Context 对象。根据您自己的观察,我假设两者的上下文是相同的(即在幕后,应用程序类调用后一个函数来填充基类的上下文部分或发生一些等效的操作)。如果您只需要一个上下文,那么调用哪个函数并不重要。
To answer the question, getApplication() returns an Application object and getApplicationContext() returns a Context object. Based on your own observations, I would assume that the Context of both are identical (i.e. behind the scenes the Application class calls the latter function to populate the Context portion of the base class or some equivalent action takes place). It shouldn't really matter which function you call if you just need a Context.