getContext(),getApplicationContext(),getBaseContext()和"this"之间的区别

iCu*_*ous 535 android this android-context

是什么区别getContext(),getApplicationContext(),getBaseContext(),和" this"?

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

Ale*_*cas 510

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

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

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

  • 那"这个"怎么样? (54认同)
  • `this`和`getContext()`并不总是相同,例如在Activity类中,你可以使用`this`,因为`Activity`继承自`Context`但方法`getContext()`不在`Activity`类中.@mikedroid @KCRaju (39认同)
  • + CooL i3oY与getContext相同 (16认同)
  • 实际上我很困惑,什么是正确的上下文定义? (13认同)
  • "this"和getContext()都是一样的 (10认同)
  • `this`给出了它所在类的一个实例,它可以是任何类,不一定是上下文.如果你在Activity类中使用它,那么`this`将是`Context`的一个实例. (2认同)
  • “ getBaseContext()”可能需要一个示例来进行更多解释。 (2认同)

Mik*_*ren 79

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

该方法getBaseContext()仅在您拥有时才有意义ContextWrapper.Android提供了一个ContextWrapper围绕现有的类创建的类Context:

ContextWrapper wrapper = new ContextWrapper(context);
Run Code Online (Sandbox Code Playgroud)

使用a的好处ContextWrapper是它允许您"在不改变原始上下文的情况下修改行为".例如,如果您有一个被调用的活动,myActivity则可以使用View与以下内容不同的主题创建myActivity:

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

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

方法getBaseContext()可用于访问ContextWrapper包装的"基本"上下文.您可能需要访问"基础"上下文,例如,检查它是否是a Service,Activity或者Application:

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");
    }
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我会说,这是一个被接受之后最重要的答案. (17认同)
  • 我会说"ContextWrapper"的存在是Android框架开发人员做出的最糟糕的决定之一.当他们意识到他们创建了一个完整的God Objects系列,而不是做正确的事情并将代码重构为Single Responsibility时,他们添加了一个丑陋的黑客,允许通过深化继承树来改变Context行为.糟糕的软件工程最糟糕.至于我们,开发人员,恕我直言,没有人应该使用`getBaseContext()`或`ContextWrapper`.如果你这样做 - 这是一个巨大的"代码味道". (4认同)

Jay*_*tel 38

getApplicationContext() - 返回在应用程序中运行的所有活动的上下文.

getBaseContext() - 如果要从应用程序中的其他上下文访问Context,则可以访问.

getContext() - 仅返回当前运行活动的上下文视图.


tez*_*tez 28

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

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

由于Activity是子类Context,可以使用它this来获取该活动的上下文


Vas*_*liy 21

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

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

当谈到Context我们应该使用哪种类型时,它变得非常复杂,因为除了作为God Object之外,Context子类的层次结构树残忍地违反了Liskov Substitution Principle.

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

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

+----------------------------+-------------+----------+---------+-----------------+-------------------+
|                            | 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               |
+----------------------------+-------------+----------+---------+-----------------+-------------------+
Run Code Online (Sandbox Code Playgroud)
  1. 应用程序可以从此处启动活动,但它需要创建新任务.这可能适合特定的用例,但可以在您的应用程序中创建非标准的堆栈行为,通常不建议或认为是良好的做法.
  2. 这是合法的,但通货膨胀将使用您运行的系统的默认主题完成,而不是在您的应用程序中定义的内容.
  3. 在Android 4.2及更高版本上,如果接收方为空,则允许用于获取粘性广播的当前值.

- 截图