活动上下文和应用程序上下文之间的区别

这让我难住了,我在Android 2.1-r8 SDK中使用这个:

ProgressDialog.show(getApplicationContext(), ....);

还有在

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

使用getApplicationContext()同时使ProgressDialogToast崩溃....这让我想到了这个问题:

活动上下文和应用程序上下文之间的实际区别是什么,尽管都使用“上下文”这个词?

151037 次浏览

它们都是上下文的实例,但是应用程序实例绑定到应用程序的生命周期,而活动实例绑定到活动的生命周期。因此,他们可以访问有关应用程序环境的不同信息。

如果你阅读getApplicationContext的文档,它注意到你只应该在需要一个生命周期与当前上下文分离的上下文时使用这个。这在你的两个例子中都不适用。

Activity上下文大概有一些关于当前活动的信息,这些信息是完成这些调用所必需的。如果您显示准确的错误消息,则可能能够指出它究竟需要什么。

但通常情况下,使用活动上下文,除非您有很好的理由不这样做。

这显然是API设计的缺陷。首先,活动上下文和应用程序上下文是完全不同的对象,因此使用上下文的方法参数应该直接使用ApplicationContextActivity,而不是使用父类Context。 其次,文档应该明确指定使用或不使用哪个上下文。< / p >

我认为原因是ProgressDialog附加到支撑ProgressDialog的活动,因为对话框在活动被销毁后不能保留,因此它需要传递this(ActivityContext),它也随着活动被销毁,而ApplicationContext即使在活动被销毁后仍然保留。

我认为当所有东西都需要屏幕来显示(按钮、对话框、布局……)时,我们必须使用上下文活动,而所有东西都不需要屏幕来显示或处理(吐司、服务电话、联系人……),我们可以使用应用程序上下文

我发现这个表格对于决定何时使用不同类型的上下文非常有用:

enter image description here

  1. 应用程序可以从这里启动一个Activity,但它需要创建一个新任务。这可能适合特定的用例,但会在应用程序中创建非标准的反向堆栈行为,通常不推荐或不认为这是一个好的实践。
  2. 这是合法的,但是膨胀将使用您正在运行的系统的默认主题来完成,而不是应用程序中定义的主题。
  3. 在android4.2及以上版本中,如果接收端为空则允许,用于获取粘滞广播的当前值。

如果需要绑定到具有全局作用域的Context的内容,请使用getApplicationContext()。

如果您使用Activity,那么新的Activity实例将有一个引用,该引用具有对旧Activity的隐式引用,并且旧Activity不能被垃圾收集。

当你直接从主屏幕启动应用程序时,你可以看到这两种上下文之间的区别,当你的应用程序通过共享意图从另一个应用程序启动时。

下面是@CommonSenseCode提到的“非标准反向堆栈行为”的实际示例:

假设你有两个相互通信的应用程序,App1App2

从启动器启动App2: MainActivity。然后从MainActivity启动App2: SecondaryActivity。在这里,无论是使用活动上下文还是应用程序上下文,两个活动都存在于同一个任务中,这是可以的(假设您使用了所有标准启动模式和意图标志)。你可以返回MainActivity,在最近的应用中,你只有一个任务。

假设现在你在App1中,并以共享意图(ACTION_SEND或ACTION_SEND_MULTIPLE)启动App2: MainActivity。然后从那里尝试启动App2: SecondaryActivity(总是带有所有标准启动模式和意图标志)。 结果是:

  • 如果你启动App2:SecondaryActivity与应用程序上下文在Android <你不能发射中的所有活动。我已经尝试了android 7和8,SecondaryActivity总是在一个新任务中启动(我猜是因为App2:SecondaryActivity是与App2应用程序上下文一起启动的,但你来自App1,你没有直接启动App2应用程序。也许在引擎盖android识别,并使用FLAG_ACTIVITY_NEW_TASK)。这可以是好的或坏的取决于你的需要,因为我的应用程序是坏的 在Android 10上,应用程序崩溃带有消息
    . b0 从Activity上下文外部调用startActivity()需要FLAG_ACTIVITY_NEW_TASK标志。这真是你想要的吗?”。< br > 所以要让它在Android 10上工作,你必须使用FALG_ACTIVITY_NEW_TASK,你不能在同一个任务中运行所有的活动 正如你所看到的,android版本之间的行为是不同的,很奇怪

  • 如果你启动带有活动上下文的App2:SecondaryActivity,一切都很顺利,你可以在同一个任务中运行所有的活动,从而产生线性的反向堆栈导航。

我希望我添加了一些有用的信息