何时调用活动上下文或应用程序上下文?

发布于 2024-12-02 21:06:54 字数 368 浏览 4 评论 0原文

我不完全理解活动上下文与应用程序上下文。

据我所知,到目前为止,每个都是其类的一个实例,这意味着一些程序员建议您尽可能频繁地使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

や莫失莫忘 2024-12-09 21:06:54

getApplicationContext() 几乎总是错误的。 女士。 Hackborn(以及其他)已经非常明确地表明,当您知道为什么使用时,您使用getApplicationContext() >getApplicationContext(),并且仅当您需要使用getApplicationContext()时。

坦率地说,“一些程序员”使用 getApplicationContext() (或较小程度的 getBaseContext()),因为他们的 Java 经验有限。它们实现一个内部类(例如,Activity 中的 ButtonOnClickListener)并需要一个 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 use getApplicationContext() when you know why you are using getApplicationContext() and only when you need to use getApplicationContext().

To be blunt, "some programmers" use getApplicationContext() (or getBaseContext(), to a lesser extent) because their Java experience is limited. They implement an inner class (e.g., an OnClickListener for a Button in an Activity) and need a Context. Rather than using MyActivity.this to get at the outer class' this, they use getApplicationContext() or getBaseContext() to get a Context object.

You only use getApplicationContext() when you know you need a Context for something that may live longer than any other likely Context you have at your disposal. Scenarios include:

  • Use getApplicationContext() if you need something tied to a Context that itself will have global scope. I use getApplicationContext(), for example, in WakefulIntentService, for the static WakeLock to be used for the service. Since that WakeLock is static, and I need a Context to get at PowerManager to create it, it is safest to use getApplicationContext().

  • Use getApplicationContext() when you bind to a Service from an Activity, if you wish to pass the ServiceConnection (i.e., the handle to the binding) between Activity instances via onRetainNonConfigurationInstance(). Android internally tracks bindings via these ServiceConnections and holds references to the Contexts that create the bindings. If you bind from the Activity, then the new Activity instance will have a reference to the ServiceConnection which has an implicit reference to the old Activity, and the old Activity cannot be garbage collected.

Some developers use custom subclasses of Application for their own global data, which they retrieve via getApplicationContext(). That's certainly possible. I prefer static data members, if for no other reason than you can only have one custom Application object. I built one app using a custom Application 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 that Activity does. Various things you will try to do with this Context will fail, mostly related to the GUI.

  • It can create memory leaks, if the Context from getApplicationContext() holds onto something created by your calls on it that you don't clean up. With an Activity, if it holds onto something, once the Activity gets garbage collected, everything else flushes out too. The Application object remains for the lifetime of your process.

回眸一遍 2024-12-09 21:06:54

我认为 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.

通知家属抬走 2024-12-09 21:06:54

我使用此表作为何时使用不同类型的上下文的指导,例如应用程序上下文(即: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:

enter image description here

All merits go to original author here for more info.

弱骨蛰伏 2024-12-09 21:06:54

使用哪个上下文?

有两种类型的上下文:

  1. 应用程序上下文与应用程序相关联,并且在应用程序的整个生命周期中始终保持不变 - 它不会改变。因此,如果您使用 Toast,则可以使用应用程序上下文甚至活动上下文(两者),因为 Toast 可以从应用程序中的任何位置显示,并且不会附加到特定窗口。但是有很多例外,其中一个例外是当您需要使用或传递活动上下文时。

  2. 活动上下文与活动相关联,如果活动被销毁,活动上下文也会被销毁 - 单个应用程序可能有多个活动(很有可能)。有时您绝对需要活动上下文句柄。例如,如果您启动一个新活动,则需要在其 Intent 中使用活动上下文,以便新启动的活动在活动堆栈方面连接到当前活动。但是,您也可以使用应用程序的上下文来启动新活动,但您需要设置标志 Intent.FLAG_ACTIVITY_NEW_TASK 意图将其视为新任务。

让我们考虑一些情况:

  • MainActivity.this 指的是扩展 Activity 类的 MainActivity 上下文,但基类(活动)也扩展了 Context 类,因此它可用于提供活动上下文。< /p>

  • getBaseContext() 提供活动上下文。

  • getApplication() 提供应用程序上下文。

  • getApplicationContext() 还提供应用程序上下文。

有关更多信息,请查看此链接

Which context to use?

There are two types of Context:

  1. 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.

  2. 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.

江挽川 2024-12-09 21:06:54

我想知道为什么不对其支持的每个操作使用应用程序上下文。最后,它降低了内存泄漏和缺少 getContext() 或 getActivity() 空检查的机会(当使用注入的应用程序上下文或通过应用程序的静态方法获取时)。声明,例如 女士的声明。 Hackborn 仅在需要时才使用应用程序上下文,如果没有解释原因,这对我来说似乎没有说服力。但我似乎找到了一个不发誓的原因:

发现某些不遵循这些规则的 Android 版本/设备组合存在问题。例如,如果我有一个传递上下文的广播接收器,并且我将该上下文转换为应用程序上下文,然后尝试在应用程序上下文上调用 registerReceiver() ,那么在很多情况下这都可以正常工作,但也有很多情况下我得到由于 ReceiverCallNotAllowedException 导致崩溃。这些崩溃发生在从 API 15 到 22 的各种 Android 版本上。
https://possiblemobile.com/2013/06/context/#comment-2443283153< /a>


因为不能保证下表中应用程序上下文支持的所有操作都适用于所有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:

have found that there are issues on some Android version / device combinations that do not follow these rules. For instance, if I have a BroadcastReceiver that is passed a Context and I convert that Context to an Application Context and then try to call registerReceiver() on the Application Context there are many instances where this works fine, but also many instances where I get a crash because of a ReceiverCallNotAllowedException. These crashes occur on a wide range of Android versions from API 15 up to 22.
https://possiblemobile.com/2013/06/context/#comment-2443283153

Because it's not guaranteed that all operations described as supported by Application Context in the table below will work on all Android devices!
enter image description here

柒七 2024-12-09 21:06:54

何时应该使用活动上下文与应用程序上下文的两个很好的例子是当显示 Toast 消息或内置对话框消息时,因为使用应用程序上下文将导致异常:

ProgressDialog.show(this, ....);

或者

Toast t = Toast.makeText(this,....);

这两者都需要来自活动上下文的信息应用程序上下文中未提供。

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:

ProgressDialog.show(this, ....);

or

Toast t = Toast.makeText(this,....);

Both of these need information from the Activity context that is not provided in the Application context.

素罗衫 2024-12-09 21:06:54

应用程序上下文一直存在直到您的应用程序处于活动状态,并且它不依赖于活动生命周期,而是上下文保持对象长期存在。如果您临时使用对象,那么此时使用的应用程序上下文活动上下文完全与应用程序上下文相反。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文