getContext(), getApplicationContext(), getBaseContext()和“this”之间的区别是什么?

虽然这是一个简单的问题,但我无法理解它们之间的基本区别。如果可能,请举一些简单的例子。


当前回答

上下文是:

一个抽象类,它的实现由Android系统提供。 它允许访问特定于应用程序的资源和类,以及 对应用程序级操作的向上调用,例如启动活动, 广播和接收意图等。

其他回答

上下文是:

一个抽象类,它的实现由Android系统提供。 它允许访问特定于应用程序的资源和类,以及 对应用程序级操作的向上调用,例如启动活动, 广播和接收意图等。

“什么是Context”是Android世界中最难回答的问题之一。

上下文定义了访问系统资源、检索应用程序的静态资产、检查权限、执行UI操作等等的方法。从本质上讲,上下文是生产环境中上帝对象反模式的一个例子。

当涉及到我们应该使用哪种上下文时,它变得非常复杂,因为除了是上帝对象之外,上下文子类的层次树粗暴地违反了利斯科夫替换原则。

这篇博客文章(现在来自Wayback Machine)试图总结上下文类在不同情况下的适用性。

为了完整起见,让我从那篇文章中复制主表:

+----------------------------+-------------+----------+---------+-----------------+-------------------+ | | Application | Activity | Service | ContentProvider | BroadcastReceiver | +----------------------------+-------------+----------+---------+-----------------+-------------------+ | Show a Dialog | NO | YES | NO | NO | NO | | Start an Activity | NO¹ | YES | NO¹ | NO¹ | NO¹ | | Layout Inflation | NO² | YES | NO² | NO² | NO² | | Start a Service | YES | YES | YES | YES | YES | | Bind to a Service | YES | YES | YES | YES | NO | | Send a Broadcast | YES | YES | YES | YES | YES | | Register BroadcastReceiver | YES | YES | YES | YES | NO³ | | Load Resource Values | YES | YES | YES | YES | YES | +----------------------------+-------------+----------+---------+-----------------+-------------------+ 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.

这个:当前类对象

getContext():返回当前活动的上下文

getApplicationContext():返回应用程序中正在运行的所有活动

大多数答案已经涵盖了getContext()和getApplicationContext(),但很少解释getBaseContext()。

getBaseContext()方法只在你有一个contexttwrapper时才有用。 Android提供了一个ContextWrapper类,它是围绕一个现有的Context创建的,使用:

ContextWrapper wrapper = new ContextWrapper(context);

使用ContextWrapper的好处是,它允许你“在不改变原始上下文的情况下修改行为”。例如,如果你有一个名为myActivity的活动,那么可以创建一个与myActivity主题不同的视图:

ContextWrapper customTheme = new ContextWrapper(myActivity) {
  @Override
  public Resources.Theme getTheme() { 
    return someTheme;
  }
}
View myView = new MyView(customTheme);

ContextWrapper is really powerful because it lets you override most functions provided by Context including code to access resources (e.g. openFileInput(), getString()), interact with other components (e.g. sendBroadcast(), registerReceiver()), requests permissions (e.g. checkCallingOrSelfPermission()) and resolving file system locations (e.g. getFilesDir()). ContextWrapper is really useful to work around device/version specific problems or to apply one-off customizations to components such as Views that require a context.

getBaseContext()方法可用于访问ContextWrapper所包装的“基本”上下文。你可能需要访问“base”上下文,例如,检查它是一个服务,活动还是应用程序:

public class CustomToast {
  public void makeText(Context context, int resId, int duration) {
    while (context instanceof ContextWrapper) {
      context = context.baseContext();
    }
    if (context instanceof Service)) {
      throw new RuntimeException("Cannot call this from a service");
    }
    ...
  }
}

或者如果你需要调用一个方法的“unwrapped”版本:

class MyCustomWrapper extends ContextWrapper {
  @Override
  public Drawable getWallpaper() {
    if (BuildInfo.DEBUG) {
      return mDebugBackground;
    } else {
      return getBaseContext().getWallpaper();
    }
  }
}

从这个文档

我明白你应该用:

尝试使用上下文应用程序而不是上下文活动