关于android:getContext(),getApplicationContext(),getBaseContext()和“this”之间的区别

Difference between getContext() , getApplicationContext() , getBaseContext() and “this”

getContext()getApplicationContext()getBaseContext()和"this"之间有什么区别?

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


  • View.getContext():返回视图当前运行的上下文。通常是当前活动的Activity。

  • Activity.getApplicationContext():返回整个应用程序的上下文(所有活动在其中运行的进程)
    的)。如果需要,请使用此代替当前的Activity上下文
    上下文绑定到整个应用程序的生命周期,而不仅仅是
    当前的活动。

  • ContextWrapper.getBaseContext():如果您需要从另一个上下文中访问Context,则使用ContextWrapper。该
    从内部引用的Context是通过访问ContextWrapper
    getBaseContext()。


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

仅当ContextWrapper时,方法getBaseContext()才有意义。
Android提供了一个ContextWrapper类,它使用以下内容围绕现有的Context创建:

1
ContextWrapper wrapper = new ContextWrapper(context);

使用ContextWrapper的好处是它允许您"修改行为而不更改原始上下文"。例如,如果您有一个名为myActivity的活动,那么可以使用与myActivity不同的主题创建View

1
2
3
4
5
6
7
ContextWrapper customTheme = new ContextWrapper(myActivity) {
  @Override
  public Resources.Theme getTheme() {
    return someTheme;
  }
}
View myView = new MyView(customTheme);

ContextWrapper非常强大,因为它可以覆盖Context提供的大多数功能,包括访问资源的代码(例如openFileInput()getString()),与其他组件交互(例如sendBroadcast()registerReceiver()),请求权限(例如checkCallingOrSelfPermission())和解析文件系统位置(例如getFilesDir())。 ContextWrapper对于解决特定于设备/版本的问题或将一次性自定义应用于需要上下文的视图等组件非常有用。

方法getBaseContext()可用于访问ContextWrapper包含的"基本"上下文。如果需要,可能需要访问"基本"上下文,例如,检查它是ServiceActivity还是Application

1
2
3
4
5
6
7
8
9
10
11
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");
    }
    ...
  }
}

或者,如果您需要调用方法的"解包"版本:

1
2
3
4
5
6
7
8
9
10
class MyCustomWrapper extends ContextWrapper {
  @Override
  public Drawable getWallpaper() {
    if (BuildInfo.DEBUG) {
      return mDebugBackground;
    } else {
      return getBaseContext().getWallpaper();
    }
  }
}


getApplicationContext() - Returns the context for all activities running in application.

getBaseContext() - If you want to access Context from another context within application you can access.

getContext() - Returns the context view only current running activity.


Context向新创建的组件提供有关ActvityApplication的信息。

应将相关的Context提供给新创建的组件(无论是应用程序上下文还是活动上下文)

由于ActivityContext的子类,因此可以使用this来获取该活动的上下文


"上下文是什么"这个问题是Android世界中最困难的问题之一。

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

当我们应该使用哪种Context时,它变得非常复杂,因为除了作为God Object之外,Context子类的层次结构树残忍地违反了Liskov替换原则。

此博客文章试图在不同情况下总结Context类的适用性。

让我从该帖子中复制主表以确保完整性:

1
2
3
4
5
6
7
8
9
10
11
12
+----------------------------+-------------+----------+---------+-----------------+-------------------+
|                            | Application | Activity | Service | ContentProvider | BroadcastReceiver |
+----------------------------+-------------+----------+---------+-----------------+-------------------+
| Show a Dialog              | NO          | YES      | NO      | NO              | NO                |
| Start an Activity          | NO1         | YES      | NO1     | NO1             | NO1               |
| Layout Inflation           | NO2         | YES      | NO2     | NO2             | NO2               |
| 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             | NO3               |
| 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.
  • screenshot


    一段上下文的UML图

    enter image description here


    从这个文档

    我明白你应该使用:

    Try using the context-application instead of a context-activity


    getApplicationContext()

    this is used for application level and refer to all activities.

    getContext()和getBaseContext()

    is most probably same .these are reffered only current activity which is live.

    这个

    is refer current class object always.