什么时候调用活动上下文或应用程序上下文?

关于这两种情况是什么,已经有很多帖子了。但我还是不太明白

就我目前的理解: 每一个都是它的类的实例,这意味着一些程序员建议你尽可能多地使用this.getApplicationContext(),以不“泄漏”任何内存。这是因为另一个this(获取Activity实例上下文)指向一个Activity,该Activity在用户每次倾斜手机或离开应用程序时被销毁。显然垃圾收集器(GC)没有捕获,因此使用太多的内存..< / p >

但是谁能想出一些真正好的编码示例,其中使用this(获得当前Activity实例的上下文)是正确的事情,而应用程序上下文将是无用的/错误的?

81297 次浏览

当你使用活动上下文和应用程序上下文时,有两个很好的例子,当显示Toast消息或内置对话框消息时,使用应用程序上下文会导致异常:

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

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

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

getApplicationContext()几乎总是错误的。Hackborn女士(其中)已经非常明确地表明,当你知道为什么你正在使用getApplicationContext()时,你只有使用getApplicationContext(),并且只有当你需要使用getApplicationContext()时。

坦率地说,“一些程序员”使用getApplicationContext()(或getBaseContext(),在较小程度上),因为他们的Java经验有限。它们实现了一个内部类(例如,Activity中的ButtonOnClickListener),并且需要Context。它们不是使用MyActivity.this来获取外部类的this,而是使用getApplicationContext()getBaseContext()来获取Context对象。

只有使用getApplicationContext()当你知道,你需要一个Context的东西可能比任何其他可能的Context在你的处置。场景包括:

  • 如果你需要某个绑定到Context的对象,并且该对象本身具有全局作用域,请使用getApplicationContext()。例如,我在WakefulIntentService中使用getApplicationContext(),用于服务使用的静态WakeLock。由于WakeLock是静态的,并且我需要一个Context来获取PowerManager来创建它,因此使用getApplicationContext()是最安全的。

  • 当你从Activity绑定到Service时,如果你想通过onRetainNonConfigurationInstance()Activity实例之间传递ServiceConnection(即绑定的句柄),请使用getApplicationContext()。Android内部通过这些ServiceConnections跟踪绑定,并保存对创建绑定的Contexts的引用。如果你从Activity绑定,那么新的Activity实例将有一个对ServiceConnection的引用,该引用有一个对旧的Activity的隐式引用,并且旧的Activity不能被垃圾收集。

一些开发人员使用Application的自定义子类用于他们自己的全局数据,他们通过getApplicationContext()检索这些数据。这当然是可能的。我更喜欢静态数据成员,如果没有其他原因,你只能有一个自定义Application对象。我使用自定义Application对象构建了一个应用程序,发现它很痛苦。哈克伯恩女士也同意这一观点

以下是为什么无论你去哪里,都要使用getApplicationContext()的原因:

  • 它不是一个完整的Context,支持Activity所做的一切。你将尝试用这个Context做的各种事情将失败,主要与GUI有关

  • 如果getApplicationContext()中的Context保留了你对它的调用所创建的东西,而你没有清理它,它就会造成内存泄漏。对于Activity,如果它持有某些东西,一旦Activity被垃圾收集,其他所有东西也会被清除。Application对象在进程的生命周期中一直存在。

我认为有很多东西在SDK站点上记录得很差,这是其中之一。我要说的是,似乎默认使用应用程序上下文更好,只有在真正需要时才使用活动上下文。我所见过的唯一需要活动上下文的地方是进度对话框。SBERG412声称你必须为toast消息使用一个活动上下文,然而Android文档清楚地显示了一个正在使用的应用程序上下文。由于这个谷歌示例,我总是使用应用程序上下文进行toast。如果这样做是错误的,那么谷歌在这里犯了错误。

这里有更多的思考和回顾:

对于toast消息,谷歌开发指南使用应用程序上下文并显式地说使用它: 烤面包的通知 < / p > 在Dev指南的对话框部分,您可以看到一个AlertDialog。生成器使用应用程序上下文,然后进度条使用活动上下文。谷歌不能解释这一点。 对话框 < / p >

当您希望处理配置更改(如方向更改),并且希望保留需要上下文(如视图)的对象时,使用应用程序上下文似乎是一个很好的理由。运行时间变化 使用活动上下文需要注意,它可能会产生泄漏。这可以通过保留视图的应用程序上下文来避免(至少这是我的理解)。在我编写的应用程序中,我打算使用应用程序上下文,因为我试图在方向改变时保留一些视图和其他东西,我仍然希望活动在方向改变时被销毁和重新创建。因此,我必须使用应用程序上下文来避免内存泄漏(参见避免内存泄漏)。对我来说,使用应用程序上下文而不是活动上下文似乎有很多很好的理由,而且对我来说,它似乎比活动上下文使用得更频繁。这就是我读过的许多Android书籍所做的,这也是我所看到的谷歌示例所做的

谷歌文档确实使它看起来在大多数情况下使用应用程序上下文是完全没问题的,而且实际上在它们的示例(至少在我看到的示例中)中使用应用程序上下文比使用活动上下文更频繁。如果使用应用程序上下文确实存在这样的问题,那么谷歌确实需要更加强调这一点。他们需要讲清楚,他们需要重做一些例子。我不会把这完全归咎于缺乏经验的开发人员,因为权威(谷歌)确实让使用应用程序上下文看起来不是问题。

应用程序上下文只活直到您的应用程序激活为止,它不依赖于活动生命周期,而是上下文保持对象长期存在。如果你临时使用的对象,则使用应用程序上下文,而活动背景则完全在应用程序上下文的相反位置使用。

使用哪个上下文?

有两种类型的上下文:

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

  2. 活动上下文与活动相关联,如果活动被销毁,则可以销毁——单个应用程序可能有多个活动(很可能)。有时你绝对需要activity context句柄。例如,如果你启动一个新活动,你需要在它的Intent中使用活动上下文,这样新的启动活动就会以活动堆栈的形式连接到当前活动。然而,你也可以使用应用程序的上下文来启动一个新活动,但随后你需要设置标志Intent.FLAG_ACTIVITY_NEW_TASK,意图将其视为一个新任务。

让我们考虑一些情况:

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

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

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

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

有关更多信息,请检查这个链接

我使用这个表来指导何时使用不同类型的Context,例如应用程序上下文(即:getApplicationContext())和活动背景,还有BroadcastReceiver上下文:

enter image description here

更多信息请访问原作者在这里

我想知道为什么不使用应用程序上下文的每一个操作,它支持。最后,它降低了内存泄漏和getContext()或getActivity()缺失空检查的可能性(当使用注入的应用程序上下文或通过静态方法从application获得时)。语句,比如Hackborn女士只在需要时使用应用程序上下文的语句,如果没有解释为什么,对我来说似乎没有说服力。但我似乎找到了一个不明确的原因:

发现一些Android版本/设备组合不遵守这些规则。例如,如果我有一个BroadcastReceiver,它传递了一个上下文,我将该上下文转换为应用程序上下文,然后尝试在应用程序上下文上调用registerReceiver(),有许多实例可以正常工作,但也有许多实例,因为ReceiverCallNotAllowedException而导致崩溃。这些崩溃发生在广泛的Android版本上,从API 15到22。 https://possiblemobile.com/2013/06/context/#comment-2443283153 < / p >

因为不能保证下表中Application Context所支持的所有操作都能在所有Android设备上运行! enter image description here < / p >