Answers:
getApplicationContext()
几乎总是错的。Hackborn女士(等等)已经非常明确,你只用getApplicationContext()
当你知道为什么你使用getApplicationContext()
,只有当你需要使用getApplicationContext()
。
直白地说,“某些程序员” 之所以使用getApplicationContext()
(或getBaseContext()
程度较小)是因为他们的Java经验有限。他们实现了一个内部类(例如,in中的OnClickListener
for ),并且需要a 。他们使用或获取对象,而不是使用“ 获取外部类” 。Button
Activity
Context
MyActivity.this
this
getApplicationContext()
getBaseContext()
Context
你只用getApplicationContext()
当你知道你需要Context
的东西,可以活得比其他任何可能Context
您在您的处置。场景包括:
使用getApplicationContext()
,如果你需要的东西绑在Context
本身将具有全局作用域。我在中使用getApplicationContext()
,例如,WakefulIntentService
将静态WakeLock
用于服务。既然那WakeLock
是静态的,并且我需要Context
先PowerManager
进行创建,那么使用它是最安全的getApplicationContext()
。
如果您希望通过绑定实例之间的(即绑定的句柄),则从getApplicationContext()
绑定到时使用。Android通过这些内部跟踪绑定,并保留对创建绑定的的引用。如果从进行绑定,则新实例将具有对的引用,而该引用具有对旧的隐式引用,并且无法对旧实例进行垃圾回收。Service
Activity
ServiceConnection
Activity
onRetainNonConfigurationInstance()
ServiceConnections
Contexts
Activity
Activity
ServiceConnection
Activity
Activity
一些开发人员将自定义子类的Application
用作自己的全局数据,然后通过进行检索getApplicationContext()
。当然有可能。我更喜欢静态数据成员,如果出于其他原因,您只能拥有一个自定义Application
对象。我使用一个自定义Application
对象构建了一个应用程序,发现它很痛苦。哈克伯恩女士也同意这一立场。
以下是无论您在何处都不使用的原因getApplicationContext()
:
它不是完整的Context
,支持所做的一切Activity
。您将尝试执行的各种操作Context
将失败,主要与GUI有关。
如果Context
from getApplicationContext()
保留了您不清除的调用所创建的某些内容,则可能导致内存泄漏。使用Activity
,如果它保留了某物,则一旦Activity
收集到垃圾,其他所有内容也将被冲洗掉。该Application
对象将在过程的整个生命周期中保留。
getApplicationContext()
在确切知道为什么在给定情况下需要它时才使用。扩大布局?使用活动。绑定到服务,您需要该绑定来承受配置更改吗?使用getApplicationContext()
,因此绑定不绑定到Activity
实例。
我认为SDK网站上记录的东西很多,这就是其中之一。我要声明的是,似乎最好默认使用应用程序上下文,而仅在确实需要时才使用活动上下文。我见过的唯一需要活动上下文的地方是进度对话框。SBERG412声称您必须在活动消息中使用活动上下文,但是Android文档清楚地显示了正在使用的应用程序上下文。由于这个Google示例,我一直将应用程序上下文用于烤面包。如果这样做是错误的,那么Google会将球丢在这里。
这里还有更多要考虑和审查的内容:
对于Toast消息,《 Google Dev Guide》使用应用程序上下文,并明确地说要使用它: Toast Notifications
在开发指南的对话框部分中,您将看到AlertDialog.Builder使用应用程序上下文,然后进度栏使用活动上下文。Google对此没有解释。 对话方块
使用应用程序上下文似乎是一个很好的理由,当您想要处理诸如方向更改之类的配置更改,并且想要保留需要诸如Views之类的上下文的对象时。如果您在此处查看:运行时更改 关于使用活动上下文的警告,这会导致泄漏。可以通过在应用程序上下文中保留要保留的视图来避免这种情况(至少是我的理解)。在我正在编写的应用程序中,我打算使用应用程序上下文,因为我试图保留方向更改中的某些视图和其他内容,并且我仍然希望活动能够在方向更改时销毁并重新创建。因此,我必须使用应用程序上下文来避免内存泄漏(请参阅避免内存泄漏)。)。对我来说,似乎有很多充分的理由使用应用程序上下文而不是活动上下文,并且对我来说,您似乎比活动上下文经常使用它。这就是我看过的许多Android书籍所要做的,也是我所看到的许多Google示例所要做的。
Google文档确实使得在大多数情况下使用应用程序上下文看起来非常好,实际上,在它们的示例中(至少是我所看到的示例),与使用活动上下文相比,它的出现频率更高。如果使用应用程序上下文确实是一个问题,那么Google确实需要对此进行更多的强调。他们需要明确说明,并且需要重做一些示例。我不会将这完全归咎于没有经验的开发人员,因为权威机构(Google)确实使使用应用程序上下文看起来不是问题。
使用哪个上下文?
有两种类型的上下文:
应用程序上下文与应用程序相关联,并且在应用程序的整个生命周期中始终是相同的-不会改变。因此,如果您正在使用Toast,则可以使用应用程序上下文,甚至可以使用活动上下文(两者),因为Toast可以在应用程序中的任何位置显示,并且不附加到特定窗口。但是有很多例外,一种例外是当您需要使用或传递活动上下文时。
活动上下文与活动相关联,如果活动被销毁,则活动上下文可以被销毁-单个应用程序可能有多个活动(可能性更大)。有时您绝对需要活动上下文句柄。例如,如果您启动一个新活动,则需要在其Intent中使用活动上下文,以便就活动堆栈而言,新的启动活动连接到当前活动。但是,您也可以使用应用程序的上下文来启动新活动,但随后需要设置标志Intent.FLAG_ACTIVITY_NEW_TASK
以将其视为新任务。
让我们考虑一些情况:
MainActivity.this
指的是MainActivity上下文,它扩展了Activity类,但是基类(activity)也扩展了Context类,因此可以用来提供活动上下文。
getBaseContext()
提供活动上下文。
getApplication()
提供应用程序上下文。
getApplicationContext()
还提供了应用程序上下文。
有关更多信息,请检查此链接。
downloadmanager
,并且在收到完成信号时,它应显示一个对话框,例如“您要对此下载做什么?”。我的(黑客)解决方案将最新的信息保存Activity
在一个static
Application
类中,并Activity
在下载完成后请求当前的信息。但是,我怀疑这是正确的实现。TL; DR如何在应用程序中的任何位置显示AlertDialog?
我想知道为什么不对它支持的每个操作使用应用程序上下文。最后,它降低了内存泄漏的机会,并且减少了对getContext()或getActivity()的空检查(使用注入的应用程序上下文或通过Application的静态方法获取时)。像Hackborn女士仅在需要时使用Application Context的声明那样,如果没有解释原因似乎对我没有说服力。但是,似乎我发现了一个失败的原因:
发现某些Android版本/设备组合存在一些不遵循这些规则的问题。例如,如果我有一个传递了上下文的BroadcastReceiver,然后将该上下文转换为Application Context,然后尝试在Application Context上调用registerReceiver(),则有很多实例可以很好地工作,但也有很多实例可以因ReceiverCallNotAllowedException而导致崩溃。这些崩溃发生在从API 15到22的各种Android版本上 。https://possiblemobile.com/2013/06/context/#comment-2443283153
当显示Toast消息或内置Dialog消息时,应该使用Activity上下文和Application上下文的两个很好的例子,因为使用Application上下文会导致异常:
ProgressDialog.show(this, ....);
要么
Toast t = Toast.makeText(this,....);
这两个都需要来自Activity上下文的信息,而Application上下文中没有提供这些信息。
应用程序上下文处于活动状态,直到您的应用程序处于活动状态唯一,这是不依赖于活动的生命周期,但是,上下文保持对象长寿。如果您使用的对象是临时的,那时候将使用Application Context和Activity Context完全与Application Context相反。