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


565

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

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


1
有一个在第一个答案的优秀新手必看: stackoverflow.com/questions/1026973/...
ky1enamic

Answers:


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

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

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


59
那“这个”呢?
CooL i3oY 2012年

16
+ Cool i3oY与getContext相同
Mikey

13
实际上,我对上下文的正确定义感到困惑吗?
拉维

11
“ this”和getContext()都相同
KCRaju 2013年

43
this并且getContext()并不总是相同的,例如在Activity类中,可以使用,this因为Activity继承自Context但方法getContext()不在Activity类中。@mikedroid @KCRaju
Nandan

92

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

该方法getBaseContext()仅在您具有时才相关ContextWrapper。Android提供了ContextWrapper一个Context使用现有的类创建的类:

ContextWrapper wrapper = new ContextWrapper(context);

使用a的好处ContextWrapper是,它可以让您“在不更改原始上下文的情况下修改行为”。例如,如果您有一个名为的活动,myActivity则可以创建一个View主题,该主题不同于myActivity

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

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");
    }
    ...
  }
}

或者,如果您需要调用方法的“未包装”版本:

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

17
我想说,这是一个被接受之后最重要的答案。
0leg

4
我要说的是,存在ContextWrapper是Android框架开发人员做出的最糟糕的决定之一。当他们意识到自己创建了整个“上帝对象”家族时,他们没有做正确的事并将代码重构为“单一职责”,而是添加了一个丑陋的方法,可以通过加深继承树来更改上下文行为。最糟糕的软件工程。对于我们来说,开发人员,恕我直言,没人可以使用getBaseContext()ContextWrapper。如果这样做-这是巨​​大的“代码异味”。
Vasiliy

我想看完整的CustomToast代码。THANKS :)))
Alston

39

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

getBaseContext() -如果要从应用程序中的另一个上下文访问上下文,则可以访问。

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


1
请把字母A和B结合到上下文中的上下文定义中,不清楚在哪个答案中可以访问哪个上下文。
希望有帮助

29

“上下文是什么”问题是Android宇宙中最困难的问题之一。

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

当涉及到哪种类型时Context,它变得非常复杂,因为Context子类的层次树除了成为上帝对象外,还残酷地违反了《里斯科夫替代原理》。

这篇博客文章试图总结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               |
+----------------------------+-------------+----------+---------+-----------------+-------------------+
  1. 应用程序可以从此处开始一个活动,但是它需要创建一个新任务。这可能适合特定的用例,但可能会在您的应用程序中创建非标准的Back Stack行为,通常不建议这样做,也不认为这是一种好的做法。
  2. 这是合法的,但是通货膨胀将使用您正在运行的系统的默认主题完成,而不是应用程序中定义的主题。
  3. 在Android 4.2及更高版本上,如果接收器为null(用于获取即时广播的当前值),则允许使用。

屏幕截图


您链接到的很棒的博客文章!
lejonl

28

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

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

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


您对baseContext的解释在哪里?
IgorGanapolsky


0

getApplicationContext()

这用于应用程序级别并涉及所有活动。

getContext()和getBaseContext()

是最可能相同的。这些仅涉及当前的活动。

这个

总是引用当前类的对象。


0

A Context是:

  • 一个抽象类,其实现由Android系统提供。
  • 它允许访问特定于应用程序的资源和类,以及对应用程序级操作(如启动活动,广播和接收意图等)的调用。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.