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

时间:2011-09-04 11:02:12

标签: android this android-context

有很多关于这两种背景的帖子......但我仍然没有把它弄得很正确

据我所知,到目前为止: 每个都是其类的一个实例,这意味着一些程序员建议您尽可能频繁地使用this.getApplicationContext(),以免“泄漏”任何内存。这是因为其他this(获取Activity实例上下文)指向每次用户倾斜手机或离开应用程序等时被销毁的Activity。这显然是垃圾收集器(GC)不会捕获,因此使用太多内存..

但任何人都可以提出一些非常好的编码示例,使用this(获取当前Activity实例的上下文)是正确的,并且应用程序上下文将无用/错误?

7 个答案:

答案 0 :(得分:388)

getApplicationContext()几乎总是错的。 Ms. Hackborn(以及其他人)明确表示,当您知道为什么使用getApplicationContext()时,使用getApplicationContext()当您需要使用getApplicationContext()时。

说实话,“一些程序员”使用getApplicationContext()(或getBaseContext(),在较小程度上),因为他们的Java经验有限。他们实现了一个内部类(例如,OnClickListenerButton的{​​{1}}并且需要Activity。他们使用ContextMyActivity.this来获取this对象,而不是使用getApplicationContext()来获取外部类getBaseContext()

你可以随意使用。场景包括:

  • 如果您需要与Context绑定的某些内容具有全局范围,请使用getApplicationContext()。我在Context中使用Context作为服务使用的静态getApplicationContext()。由于Context是静态的,我需要getApplicationContext()WakefulIntentService来创建它,因此最安全的是使用WakeLock

  • 如果您希望传递WakeLock(即绑定句柄),则绑定到Context的{​​{1}}时使用PowerManager通过getApplicationContext()getApplicationContext()个实例之间。 Android通过这些Service在内部跟踪绑定,并保存对创建绑定的Activity的引用。如果您从ServiceConnection绑定,那么新的Activity实例将引用onRetainNonConfigurationInstance(),其中隐含引用旧ServiceConnections和旧Contexts 1}}不能被垃圾收集。

一些开发人员使用Activity的自定义子类作为他们自己的全局数据,他们通过Activity检索这些数据。这当然是可能的。我更喜欢静态数据成员,如果没有其他原因,您只能拥有一个自定义ServiceConnection对象。我使用自定义Activity对象构建了一个应用程序,发现它很痛苦。 Ms. Hackborn also agrees with this position

以下是在任何地方使用Activity的原因:

  • 这不是一个完整的Application,支持getApplicationContext()所做的一切。您尝试对此Application尝试的各种事项将失败,mostly related to the GUI

  • 如果来自Application的{​​{1}}保留在您不能清理的调用所创建的内容上,则可能会造成内存泄漏。使用getApplicationContext(),如果它保留了某些内容,一旦Context收集垃圾,其他所有内容都会被清除。 Activity对象在您的流程生命周期内保留。

答案 1 :(得分:47)

我认为SDK网站上记录的内容很多,这就是其中之一。我要提出的主张是,似乎最好默认使用应用程序上下文,并且只在需要时才使用活动上下文。我见过你需要一个活动上下文的唯一地方是进度对话框。 SBERG412声称您必须为toast消息使用活动上下文,但Android文档清楚地显示正在使用的应用程序上下文。由于这个Google示例,我总是使用应用程序上下文进行祝酒。如果这样做是错误的,那么谷歌就把球丢了。

以下是思考和审核的更多内容:

对于Toast消息,Google Dev Guide使用应用程序上下文并明确说明使用它: Toast Notifications

在开发指南的对话框部分中,您会看到AlertDialog.Builder使用应用程序上下文,然后进度条使用活动上下文。谷歌没有解释这一点。 Dialogs

使用应用程序上下文似乎是一个很好的理由,当您想要处理配置更改(如方向更改)时,您希望保留需要像Views这样的上下文的对象。如果你看这里:Run Time Changes 使用活动上下文时要小心,这可能会造成泄漏。使用具有要保留的视图的应用程序上下文(至少这是我的理解)可以避免这种情况。在我正在编写的应用程序中,我打算使用应用程序上下文,因为我试图在方向更改上保留一些视图和其他内容,并且我仍然希望在方向更改时销毁和重新创建活动。因此,我必须使用应用程序上下文不会导致内存泄漏(请参阅Avoiding memory Leaks)。对我而言,似乎有很多充分的理由使用应用程序上下文而不是活动上下文,对我来说,几乎看起来你会比活动上下文更频繁地使用它。这就是我经历过的许多Android书籍似乎都在做的事情,而这就是我见过的那些Google案例。

Google文档确实使得在大多数情况下使用应用程序上下文看起来非常好,并且实际上比在示例中使用活动上下文更频繁(至少我见过的示例)。如果使用应用程序上下文确实是一个问题,那么谷歌真的需要更加重视这一点。他们需要说清楚,他们需要重做他们的一些例子。我不会完全将这归咎于没有经验的开发人员,因为权威(谷歌)真的让它看起来像使用应用程序上下文不是问题。

答案 2 :(得分:34)

我使用此表作为何时使用不同类型的上下文的指导,例如应用程序上下文(即:getApplicationContext())和活动上下文,还有 BroadcastReceiver上下文

enter image description here

所有优点都归原始作者here所有。

答案 3 :(得分:11)

  

使用哪种上下文?

有两种类型的上下文:

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

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

  3. 让我们考虑一些情况:

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

    • getBaseContext()提供活动背景。

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

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

    有关详情,请查看此link

答案 4 :(得分:4)

我想知道为什么不为它支持的每个操作使用Application Context。最后,它降低了内存泄漏的可能性,并且缺少对getContext()或getActivity()的空检查(当使用注入的应用程序上下文或通过Application中的静态方法获取时)。语句,如Ms. Hackborn仅在需要时使用应用程序上下文的语句,如果没有解释原因,对我来说似乎并不令人信服。但似乎我找到了一个不合理的原因:

  

已发现某些Android版本/设备组合存在问题但未遵循这些规则。例如,如果我有一个传递了Context的BroadcastReceiver并且我将该Context转换为Application Context然后尝试在Application Context上调用registerReceiver(),那么有很多实例可以正常工作,但是我得到的很多实例由于ReceiverCallNotAllowedException导致崩溃。这些崩溃发生在从API 15到22的各种Android版本上。   https://possiblemobile.com/2013/06/context/#comment-2443283153

因为无法保证下表中“应用程序上下文”所支持的所有操作都适用于所有Android设备! enter image description here

答案 5 :(得分:3)

当您应该使用Activity上下文与Application上下文时,两个很好的例子是在显示Toast消息或内置Dialog消息时,因为使用Application上下文会导致异常:

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

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

这两个都需要来自Activity上下文的信息,而这些信息并未在Application上下文中提供。

答案 6 :(得分:3)

应用程序上下文直播直到你的应用程序还活着并且它不依赖于活动生命周期但是,上下文保持对象长寿 。如果临时使用的对象,那个时间使用应用程序上下文活动上下文,则完全使用应用程序上下文。