When to call activity context OR application context?
有很多关于这两种背景的帖子......但我仍然没有把它弄得恰到好处
据我所知,到目前为止:
每个都是它的类的一个实例,这意味着一些程序员建议你尽可能频繁地使用
但任何人都可以想出一些非常好的编码示例,使用
说实话,"一些程序员"使用
只有当你知道自己需要一个
-
如果您需要绑定到
Context 的东西,请使用getApplicationContext() ,而Context 本身将具有全局范围。我在WakefulIntentService 中使用getApplicationContext() ,用于服务所使用的静态WakeLock 。因为WakeLock 是静态的,并且我需要Context 来获取PowerManager 来创建它,所以使用getApplicationContext() 是最安全的。 -
如果希望通过
onRetainNonConfigurationInstance() 传递Activity 实例之间的ServiceConnection (即绑定句柄),则在从Activity 绑定到Service 时使用getApplicationContext() 。 Android通过这些ServiceConnections 内部跟踪绑定,并保存对创建绑定的Contexts 的引用。如果从Activity 绑定,则新的Activity 实例将具有对ServiceConnection 的引用,该引用具有对旧Activity 的隐式引用,并且旧的Activity 不能被垃圾回收。
一些开发人员使用
以下是无论何时何地不使用
-
它不是一个完整的
Context ,支持Activity 所做的一切。您将尝试使用此Context 执行的各种操作将失败,主要与GUI有关。 -
如果
getApplicationContext() 中的Context 保留在您不能清理的调用所创建的内容上,则可能会造成内存泄漏。使用Activity ,如果它保留了某些内容,一旦Activity 被垃圾收集,其他所有内容都会被清除。Application 对象保留在进程的生命周期内。
我认为SDK网站上有很多文档记录很少,这就是其中之一。我要提出的主张是,似乎最好默认使用应用程序上下文,并且只在需要时才使用活动上下文。我见过你需要一个活动上下文的唯一地方是进度对话框。 SBERG412声称您必须为toast消息使用活动上下文,但Android文档清楚地显示正在使用的应用程序上下文。由于这个Google示例,我总是使用应用程序上下文进行祝酒。如果这样做是错误的,那么谷歌就把球丢了。
这里有更多的思考和评论:
对于Toast消息,Google Dev Guide使用应用程序上下文并明确说出要使用它:
吐司通知
在Dev指南的对话框部分中,您会看到AlertDialog.Builder使用应用程序上下文,然后进度条使用活动上下文。谷歌没有解释这一点。
对话框
使用应用程序上下文似乎是一个很好的理由,当您想要处理配置更改(如方向更改)时,您希望保留需要像Views这样的上下文的对象。如果你看这里:运行时间更改
使用活动上下文时要小心,这可能会造成泄漏。使用具有要保留的视图的应用程序上下文(至少这是我的理解)可以避免这种情况。在我正在编写的应用程序中,我打算使用应用程序上下文,因为我试图在方向更改上保留一些视图和其他内容,并且我仍然希望在方向更改时销毁和重新创建活动。因此,我必须使用应用程序上下文不会导致内存泄漏(请参阅避免内存泄漏)。对我而言,似乎有很多充分的理由使用应用程序上下文而不是活动上下文,对我来说,几乎看起来你会比活动上下文更频繁地使用它。这就是我经历过的许多Android书籍似乎都在做的事情,而这就是我见过的很多Google的例子。
谷歌文档确实使得在大多数情况下使用应用程序上下文看起来非常好,实际上比在他们的示例中使用活动上下文更频繁(至少我见过的例子)。如果使用应用程序上下文确实是一个问题,那么谷歌真的需要更加重视这一点。他们需要说清楚,他们需要重做他们的一些例子。我不会完全将这归咎于没有经验的开发人员,因为权威(谷歌)真的让它看起来好像使用应用程序上下文不是问题。
我使用此表作为何时使用不同类型的Context(如Application上下文(即:
所有优点都归原作者所有,以获取更多信息。
Which context to use?
上下文有两种类型:
应用程序上下文与应用程序相关联,并且在应用程序的整个生命周期中始终保持相同 - 它不会更改。因此,如果您正在使用Toast,则可以使用应用程序上下文甚至活动上下文(两者),因为toast可以在应用程序中的任何位置显示,并且不会附加到特定窗口。但是有许多例外,一个例外是当您需要使用或传递活动上下文时。
活动上下文与活动相关联,如果活动被销毁,则可以销毁活动上下文 - 单个应用程序可能存在多个活动(很可能)。有时你绝对需要活动上下文句柄。例如,如果启动新活动,则需要在其Intent中使用活动上下文,以便新的启动活动根据活动堆栈连接到当前活动。但是,您也可以使用应用程序的上下文来启动新活动,但是您需要将intent
让我们考虑一些情况:
-
MainActivity.this 指的是扩展Activity类的MainActivity上下文,但基类(activity)也扩展了Context类,因此它可用于提供活动上下文。 -
getBaseContext() 提供活动背景。 -
getApplication() 提供应用程序上下文。 -
getApplicationContext() 还提供应用程序上下文。
有关更多信息,请查看此链接。
我想知道为什么不为它支持的每个操作使用Application Context。最后,它降低了内存泄漏的可能性,并且缺少对getContext()或getActivity()的空检查(当使用注入的应用程序上下文或通过Application中的静态方法获取时)。声明,就像Hackborn女士仅在需要时使用应用程序上下文一样,在没有解释原因的情况下对我来说似乎并不令人信服。但似乎我找到了一个不合理的原因:
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
因为无法保证下表中的Application Context所支持的所有操作都适用于所有Android设备!
应用程序上下文实时,直到您的应用程序仅存活,并且它不依赖于活动生命周期,但上下文保持对象长期存在。如果您临时使用的对象,那个时候使用Application Context和Activity Context完全对应Application Context。
应该使用Activity上下文与Application上下文的两个很好的例子是在显示Toast消息或内置Dialog消息时,因为使用Application上下文会导致异常:
1 | ProgressDialog.show(this, ....); |
要么
1 | Toast t = Toast.makeText(this,....); |
这两者都需要来自Activity上下文的信息,而这些信息并未在Application上下文中提供。