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

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

还有在

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

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

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


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

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

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

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


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


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


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


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

An application CAN start an Activity from here, but it requires that a new task be created. This may fit specific use cases, but can create non-standard back stack behaviors in your application and is generally not recommended or considered good practice. This is legal, but inflation will be done with the default theme for the system on which you are running, not what’s defined in your application. Allowed if the receiver is null, which is used for obtaining the current value of a sticky broadcast, on Android 4.2 and above.


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

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


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

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

假设您有两个相互通信的应用程序,App1和App2。

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

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

if you launch App2:SecondaryActivity with application context on Android < 10 you cannot launch all the activities in the same task. I have tried with android 7 and 8 and the SecondaryActivity is always launched in a new task (I guess is because App2:SecondaryActivity is launched with the App2 application context but you're coming from App1 and you didn't launch the App2 application directly. Maybe under the hood android recognize that and use FLAG_ACTIVITY_NEW_TASK). This can be good or bad depending on your needs, for my application was bad. On Android 10 the app crashes with the message "Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?". So to make it work on Android 10 you have to use FALG_ACTIVITY_NEW_TASK and you cannot run all activities in the same task. As you can see the behavior is different between android versions, weird. if you launch App2:SecondaryActivity with activity context all goes well and you can run all the activities in the same task resulting in a linear backstack navigation.

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