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

Posted

技术标签:

【中文标题】getContext() 、 getApplicationContext() 、 getBaseContext() 和“this”之间的区别【英文标题】:Difference between getContext() , getApplicationContext() , getBaseContext() and "this" 【发布时间】:2012-05-25 08:24:02 【问题描述】:

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

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

【问题讨论】:

第一个答案中有一篇精彩的文章:***.com/questions/1026973/… What's the difference between the various methods to get a Context?的可能重复 【参考方案1】:

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

Activity.getApplicationContext():返回整个应用程序的上下文(所有Activity都在里面运行的进程 的)。如果需要,请使用 this 而不是当前的 Activity 上下文 与整个应用程序的生命周期相关联的上下文,而不仅仅是 当前活动。

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

【讨论】:

+CooL i3oY 同 getContext 其实我很困惑上下文的正确定义是什么?? "this" 和 getContext() 都是一样的 thisgetContext() 并不总是相同的,例如在 Activity 类中,您可以使用 this,因为 Activity 继承自 Context 但方法 getContext() 不在 Activity 类中。 @mikedroid @KCRaju this 给出了它所在类的实例,它可以是任何类,不一定是上下文。如果你在 Activity 类中使​​用它,那么 this 将是 Context 的一个实例。【参考方案2】:

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

方法getBaseContext() 仅在您拥有ContextWrapper 时才相关。 android 提供了一个 ContextWrapper 类,它是围绕现有的 Context 创建的,使用:

ContextWrapper wrapper = new ContextWrapper(context);

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

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();
    
  

【讨论】:

我想说,这是接受后最重要的答案。 我想说ContextWrapper 的存在是Android 框架开发人员做出的最糟糕的决定之一。当他们意识到他们创建了一个完整的上帝对象家族时,他们没有做正确的事情并将代码重构为单一职责,而是添加了一个丑陋的 hack,允许通过加深继承树来更改上下文行为。糟糕的软件工程是最丑陋的。至于我们,开发人员,恕我直言,任何人都不应该使用getBaseContext()ContextWrapper。如果你这样做 - 这是一个巨大的“代码气味”。 我想查看完整的CustomToast 代码。 THANKS:))) 感谢您的回答,我不知道 ContextWrapper 会这样使用!!我一直认为这是 Android 团队内部的东西。在我看来,这是预期的答案。 T H A N K S !!!【参考方案3】:

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

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

我们应该使用哪种Context,变得非常复杂,因为Context子类的层次树除了是上帝对象外,还粗暴地违反了里氏替换原则。

This blog post(现来自 Wayback Machine)试图总结 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               |
+----------------------------+-------------+----------+---------+-----------------+-------------------+
    应用程序可以从这里启动一个 Activity,但它需要创建一个新任务。这可能适合特定用例,但可能会在您的应用程序中创建非标准的回栈行为,通常不推荐或不被视为良好做法。 这是合法的,但膨胀将使用您正在运行的系统的默认主题完成,而不是您的应用程序中定义的主题。 在接收者为 null 时允许,用于获取粘性广播的当前值,在 Android 4.2 及更高版本上。

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

【参考方案5】:

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

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

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

【讨论】:

【参考方案6】:

getApplicationContext()

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

getContext() 和 getBaseContext()

很可能是相同的。这些仅引用当前的活动。

这个

总是引用当前类对象。

【讨论】:

【参考方案7】:

this:当前类对象

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

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

【讨论】:

【参考方案8】:

来自docs

我知道你应该使用:

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

【讨论】:

【参考方案9】:

Context 是:

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

【讨论】:

以上是关于getContext() 、 getApplicationContext() 、 getBaseContext() 和“this”之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

getContext() 不存在

片段中的 getContext()

SecurityContextHolder.getContext().getAuthentication() 跨请求返回 Null

为啥 Application.getContext() 返回 null? [复制]

getContext 不是函数

SecurityContextHolder.getContext().getAuthentication() 返回 null