何时调用活动上下文或应用程序上下文?
我不完全理解活动上下文与应用程序上下文。
据我所知,到目前为止,每个都是其类的一个实例,这意味着一些程序员建议您尽可能频繁地使用 this.getApplicationContext()
,以免“泄漏”任何内存。这是因为另一个 this
(获取 Activity
实例上下文)指向每次用户倾斜手机时都会被销毁的 Activity
,或者离开应用程序等,垃圾收集器(GC)显然无法捕获这些内容,因此应用程序使用了太多内存。
但是,在哪里使用 this
(获取当前 Activity
实例的上下文)是正确的,而应用程序上下文将是无用/错误的呢?
I do not fully understand the activity context vs the application context.
As I understand it so far, each is an instance of its class, which means that some programmers recommend you to use this.getApplicationContext()
as often as possible in order to not "leak" out any memory. This is because the other this
(getting the Activity
instance context) points to an Activity
that is being destroyed each time the user tilts the phone, or leave the app, etc., which the Garbage Collector (GC) apparently doesn't catch and therefore the app uses too much memory.
But where would it be right to use this
(getting the context of the current Activity
instance) and the application context would be useless/wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
getApplicationContext()
几乎总是错误的。 女士。 Hackborn(以及其他)已经非常明确地表明,当您知道为什么使用时,您仅使用
,并且仅当您需要使用getApplicationContext()
>getApplicationContext()getApplicationContext()
时。坦率地说,“一些程序员”使用
getApplicationContext()
(或较小程度的getBaseContext()
),因为他们的 Java 经验有限。它们实现一个内部类(例如,Activity
中的Button
的OnClickListener
)并需要一个Context
。他们不使用MyActivity.this
来获取外部类的this
,而是使用getApplicationContext()
或getBaseContext() 获取
Context
对象。仅当您知道您需要一个
Context
来实现比任何其他生命周期都长的东西时,才使用getApplicationContext()
您可能拥有可以使用的上下文
。场景包括:如果您需要与本身具有全局范围的
Context
绑定的某些内容,请使用getApplicationContext()
。例如,我在WakefulIntentService
中使用getApplicationContext()
,将静态WakeLock
用于服务。由于WakeLock
是静态的,并且我需要一个Context
来获取PowerManager
来创建它,因此使用getApplicationContext( )
。当您从
Activity
绑定到Service
时,如果您希望传递ServiceConnection
,请使用getApplicationContext()
通过onRetainNonConfigurationInstance()
实现Activity
实例之间的 code>(即绑定句柄)。 Android 在内部通过这些ServiceConnections
跟踪绑定,并保存对创建绑定的Contexts
的引用。如果您从Activity
绑定,则新的Activity
实例将引用ServiceConnection
,后者隐式引用旧的>Activity
,旧的Activity
无法被垃圾回收。一些开发人员将
Application
的自定义子类用于自己的全局数据,并通过getApplicationContext()
检索这些数据。这当然是可能的。我更喜欢静态数据成员,如果没有其他原因,您只能拥有一个自定义Application
对象。我使用自定义Application
对象构建了一个应用程序,发现它很痛苦。 女士。哈克伯恩也同意这一立场。以下是为什么不无论走到哪里都使用
getApplicationContext()
的原因:它不是一个完整的
Context
,支持的所有内容Activity 确实如此。您尝试使用此
Context
执行的各种操作都会失败,主要与 GUI 相关。如果
getApplicationContext()
中的Context
保留了您调用它而创建的某些内容,而您没有清理这些内容,则可能会造成内存泄漏。对于Activity
,如果它持有某些东西,一旦Activity
被垃圾回收,其他所有东西也会被清除。Application
对象在进程的生命周期内保留。getApplicationContext()
is almost always wrong. Ms. Hackborn (among others) have been very explicit that you only usegetApplicationContext()
when you know why you are usinggetApplicationContext()
and only when you need to usegetApplicationContext()
.To be blunt, "some programmers" use
getApplicationContext()
(orgetBaseContext()
, to a lesser extent) because their Java experience is limited. They implement an inner class (e.g., anOnClickListener
for aButton
in anActivity
) and need aContext
. Rather than usingMyActivity.this
to get at the outer class'this
, they usegetApplicationContext()
orgetBaseContext()
to get aContext
object.You only use
getApplicationContext()
when you know you need aContext
for something that may live longer than any other likelyContext
you have at your disposal. Scenarios include:Use
getApplicationContext()
if you need something tied to aContext
that itself will have global scope. I usegetApplicationContext()
, for example, inWakefulIntentService
, for the staticWakeLock
to be used for the service. Since thatWakeLock
is static, and I need aContext
to get atPowerManager
to create it, it is safest to usegetApplicationContext()
.Use
getApplicationContext()
when you bind to aService
from anActivity
, if you wish to pass theServiceConnection
(i.e., the handle to the binding) betweenActivity
instances viaonRetainNonConfigurationInstance()
. Android internally tracks bindings via theseServiceConnections
and holds references to theContexts
that create the bindings. If you bind from theActivity
, then the newActivity
instance will have a reference to theServiceConnection
which has an implicit reference to the oldActivity
, and the oldActivity
cannot be garbage collected.Some developers use custom subclasses of
Application
for their own global data, which they retrieve viagetApplicationContext()
. That's certainly possible. I prefer static data members, if for no other reason than you can only have one customApplication
object. I built one app using a customApplication
object and found it to be painful. Ms. Hackborn also agrees with this position.Here are reasons why not to use
getApplicationContext()
wherever you go:It's not a complete
Context
, supporting everything thatActivity
does. Various things you will try to do with thisContext
will fail, mostly related to the GUI.It can create memory leaks, if the
Context
fromgetApplicationContext()
holds onto something created by your calls on it that you don't clean up. With anActivity
, if it holds onto something, once theActivity
gets garbage collected, everything else flushes out too. TheApplication
object remains for the lifetime of your process.我认为 SDK 网站上有很多内容记录得很差,这就是其中之一。我要提出的观点是,似乎最好默认使用应用程序上下文,并且仅在真正需要时才使用活动上下文。我见过的唯一需要活动上下文的地方是进度对话框。 SBERG412 声称您必须使用 toast 消息的活动上下文,但 Android 文档清楚地显示了正在使用的应用程序上下文。由于这个 Google 示例,我一直使用应用程序上下文来进行祝酒。如果这样做是错误的,那么谷歌就失败了。
这里还有更多需要考虑和审查的内容:
对于 toast 消息,Google 开发指南使用应用程序上下文并明确说明要使用它:
Toast 通知
在开发指南的对话框部分中,您会看到 AlertDialog.Builder 使用应用程序上下文,然后进度条使用活动上下文。谷歌没有对此进行解释。
对话框
似乎使用应用程序上下文的一个很好的理由是当你想要的时候处理配置更改(例如方向更改),并且您希望保留需要上下文(例如视图)的对象。如果您查看此处:运行时更改
使用活动上下文需要注意,这可能会造成泄漏。使用具有要保留的视图的应用程序上下文可以避免这种情况(至少这是我的理解)。在我正在编写的应用程序中,我打算使用应用程序上下文,因为我试图在方向更改时保留一些视图和其他内容,并且我仍然希望在方向更改时销毁并重新创建活动。因此我必须使用应用程序上下文才不会导致内存泄漏(请参阅 避免内存泄漏)。对我来说,似乎有很多充分的理由使用应用程序上下文而不是活动上下文,而且对我来说,您似乎会比活动上下文更频繁地使用它。我读过的许多 Android 书籍似乎都是这么做的,我见过的许多 Google 示例也是这么做的。
Google 文档确实使得在大多数情况下使用应用程序上下文看起来完全没问题,而且事实上在他们的示例中(至少是我见过的示例)比使用活动上下文出现得更频繁。如果使用应用程序上下文真的是一个问题,那么谷歌确实需要更加重视这一点。他们需要说清楚,并且需要重做一些例子。我不会将这完全归咎于缺乏经验的开发人员,因为权威(Google)确实让使用应用程序上下文看起来不是问题。
I think there's a lot of stuff that is poorly documented on the SDK site, this is one of them. The claim I'm going to make is that it seems as though it's better to default to using an application context and only use an activity context when you really need to. The only place where I've ever seen that you need an activity context is for a progress dialog. SBERG412 claims that you have to use an activity context for a toast message, yet the Android docs clearly show an application context being used. I've always used application context for toasts because of this Google example. If it's wrong to do so, then Google dropped the ball here.
Here's more to think about and review:
For a toast message, the Google Dev Guide uses the application context and explicitly say's to use it:
Toast Notifications
In the dialogs section of the Dev guide, you see that an AlertDialog.Builder uses the application context, and then the progress bar uses an activity context. This isn't explained by Google.
Dialogs
It seems like a good reason to use application context is when you want to handle configuration changes like an orientation change, and you want to retain objects which need a context like Views. If you look here: Run Time Changes
There is a caution about using an activity context, which can create a leak. This can be avoided with an application context with the views that are to be retained (at least that's my understanding). In an app I'm writing, I intend to use an application context because I'm trying to hold over some views and other things on an orientation change, and I still want the activity to be destroy and recreated on orientation changes. Thus I have to use an app context to not cause a memory leak (see Avoiding memory Leaks). To me it seems there are plenty of good reasons to use the application context instead of an activity context, and to me it almost seems like you would use it more often than an activity context. That's what many Android books I've gone through seem to do, and that's what much of the Google examples I've seen do.
The Google documentation really makes it seem like using application context is perfectly fine in most cases, and in fact appears more often than using an activity context in their examples (at least the examples I've seen). If it's really such a problem to use application context, then Google really needs to place more emphasis on this. They need to make it clear, and they need to redo some of their examples. I wouldn't blame this entirely on inexperienced developers since the authority (Google) really makes it look like it's not a problem to use application contexts.
我使用此表作为何时使用不同类型的上下文的指导,例如应用程序上下文(即:
getApplicationContext()
)和活动上下文 ,还有 BroadcastReceiver 上下文:所有优点均归原作者 此处了解更多信息。
I used this table as a guidance for when to use the different types of Context such as Application context (i.e:
getApplicationContext()
) and activity context , also BroadcastReceiver context:All merits go to original author here for more info.
有两种类型的上下文:
应用程序上下文与应用程序相关联,并且在应用程序的整个生命周期中始终保持不变 - 它不会改变。因此,如果您使用 Toast,则可以使用应用程序上下文甚至活动上下文(两者),因为 Toast 可以从应用程序中的任何位置显示,并且不会附加到特定窗口。但是有很多例外,其中一个例外是当您需要使用或传递活动上下文时。
活动上下文与活动相关联,如果活动被销毁,活动上下文也会被销毁 - 单个应用程序可能有多个活动(很有可能)。有时您绝对需要活动上下文句柄。例如,如果您启动一个新活动,则需要在其 Intent 中使用活动上下文,以便新启动的活动在活动堆栈方面连接到当前活动。但是,您也可以使用应用程序的上下文来启动新活动,但您需要设置标志
Intent.FLAG_ACTIVITY_NEW_TASK
意图将其视为新任务。让我们考虑一些情况:
MainActivity.this
指的是扩展 Activity 类的 MainActivity 上下文,但基类(活动)也扩展了 Context 类,因此它可用于提供活动上下文。< /p>getBaseContext()
提供活动上下文。getApplication()
提供应用程序上下文。getApplicationContext()
还提供应用程序上下文。有关更多信息,请查看此链接。
There are two types of Context:
Application context is associated with the application and will always be same throughout the life of application -- it does not change. So if you are using Toast, you can use application context or even activity context (both) because toast can be displayed from anywhere with in your application and is not attached to a specific window. But there are many exceptions, one exception is when you need to use or pass the activity context.
Activity context is associated with to the activity and can be destroyed if the activity is destroyed -- there may be multiple activities (more than likely) with a single application. And sometimes you absolutely need the activity context handle. For example, should you launch a new activity, you need to use activity context in its Intent so that the new launching activity is connected to the current activity in terms of activity stack. However, you may use application's context too to launch a new activity but then you need to set flag
Intent.FLAG_ACTIVITY_NEW_TASK
in intent to treat it as a new task.Let's consider some cases:
MainActivity.this
refers to the MainActivity context which extends Activity class but the base class (activity) also extends Context class, so it can be used to offer activity context.getBaseContext()
offers activity context.getApplication()
offers application context.getApplicationContext()
also offers application context.For more information please check this link.
我想知道为什么不对其支持的每个操作使用应用程序上下文。最后,它降低了内存泄漏和缺少 getContext() 或 getActivity() 空检查的机会(当使用注入的应用程序上下文或通过应用程序的静态方法获取时)。声明,例如 女士的声明。 Hackborn 仅在需要时才使用应用程序上下文,如果没有解释原因,这对我来说似乎没有说服力。但我似乎找到了一个不发誓的原因:
因为不能保证下表中应用程序上下文支持的所有操作都适用于所有Android 设备!
I was wondering why not to use Application Context for every operation which it supports. In the end it lowers chance of memory leak and missing null check for getContext() or getActivity() (when using injected application context or acquired through static method from Application). Statements, like the one by Ms. Hackborn to use Application Context only if needed, don't seem convincing for me without an explanation why. But it seems that I have found an unswear why:
Because it's not guaranteed that all operations described as supported by Application Context in the table below will work on all Android devices!
何时应该使用活动上下文与应用程序上下文的两个很好的例子是当显示 Toast 消息或内置对话框消息时,因为使用应用程序上下文将导致异常:
或者
这两者都需要来自活动上下文的信息应用程序上下文中未提供。
Two great examples of when you should use Activity context vs. the Application context are when displaying either a Toast message or a built-in Dialog message as using the Application context will cause an exception:
or
Both of these need information from the Activity context that is not provided in the Application context.
应用程序上下文一直存在直到您的应用程序处于活动状态,并且它不依赖于活动生命周期,而是上下文保持对象长期存在。如果您临时使用对象,那么此时使用的应用程序上下文和活动上下文完全与应用程序上下文相反。
Application context live untill your application is alive only and it is not depend on Activity Life Cycle but, context keep object long-lived. If the object which you are used temporary, that time use Application Context and Activity Context is used totally oposite of Application Context.