题 什么是Android上的“上下文”?


在Android编程中,究竟是什么 Context 类和它用于什么?

我在开发者网站上看过它,但我无法理解它。


1581
2017-08-26 06:12


起源


相关 这个问题 - Christopher Perry
除了@ SourabSharma的出色答案(不幸的是,它不是被接受的答案),这篇博客文章通过单一责任原则的棱镜回顾上下文: techyourchance.com/single-responsibility-principle - Vasiliy


答案:


简单地说:

顾名思义,它是应用程序/对象当前状态的上下文。它允许新创建的对象了解正在发生的事情。通常,您可以调用它来获取有关程序其他部分(活动和包/应用程序)的信息。

您可以通过调用获取上下文 getApplicationContext()getContext()getBaseContext() 要么 this (当在一个延伸的类中 Context,例如Application,Activity,Service和IntentService类)。

上下文的典型用法:

  • 创建新对象: 创建新视图,适配器,侦听器:

    TextView tv = new TextView(getContext());
    ListAdapter adapter = new SimpleCursorAdapter(getApplicationContext(), ...);
    
  • 访问标准公共资源: 像LAYOUT_INFLATER_SERVICE,SharedPreferences这样的服务:

    context.getSystemService(LAYOUT_INFLATER_SERVICE)
    getApplicationContext().getSharedPreferences(*name*, *mode*);
    
  • 隐式访问组件: 关于内容提供商,广播,意图

    getApplicationContext().getContentResolver().query(uri, ...);
    

1244
2017-08-26 06:32



在你的例子中 context.getSystemService(LAYOUT_INFLATER_SERVICE),在哪里以及如何 context 界定? - Dennis
很好地解释了为什么我们在动态创建文本视图时需要上下文。但是在动态创建文本视图数组时,我们不必提及任何上下文。为什么 ? TextView [] textview = new TextView [10]; - Abhinav Arora
@AbhinavArora在定义数组时,你实际上并没有构建任何文本视图的实例(你基本上只是为它们创建空间)。在您将任何值放入该数组时,您需要预先创建的TextView,或者需要一个Context来允许您创建它们。 - mc1arke
为什么观点需要背景?例如,如果没有上下文,TextView将无法做什么? - dinosaur
没有“Context”的一段代码可以在每个具有JVM的操作系统上运行。但如果有一个上下文它应该在Android上运行。如果你想使用Android特定的东西(访问设备位置,拍照,运行后台服务等)你需要一个上下文虽然你不需要,如果你做一个http请求。可以假设上下文是Java和Android之间的桥梁。 - Faruk Toptas


Context的定义::

  • Context表示环境数据
  • 它提供对数据库等内容的访问

更简单的术语::

  • 考虑到Person-X是一家初创软件公司的首席执行官。

  • 该公司的首席架构师是该公司的首席架构师 完成公司中涉及数据库,UI等所有工作 等等

  • 现在,CEO聘请了一位新的开发人员。

  • 建筑师告诉新雇员的责任 基于新人技能的人,他是否愿意 在数据库或UI等工作

更简单的术语::

  • 这就像访问Android活动到应用程序的资源。

  • 这与您访问酒店时的情况类似,您需要早餐,午餐和 晚餐在合适的时间,对吧?

  • 入住期间,您还有许多其他的事情。你怎么 得到这些东西?

  • 您要求客房服务人员为您带来这些东西。

  • 在这里,客房服务人员是考虑到你的情况 单项活动和酒店成为您的应用程序,最后是早餐,午餐和 晚餐必须是资源。


涉及背景的事情是:

  1. 加载资源。
  2. 发起一项新活动。
  3. 创建视图。
  4. 获得系统服务。

Context是基类 活动服务应用 ......等

另一种描述这种情况的方法:考虑上下文作为电视中的电视和频道的遥控器是资源,服务,使用意图等 - 这里,遥控器充当访问所有不同资源到前台的访问。

  • 因此,Remote可以访问资源,服务,使用意图等渠道....
  • 同样......无论谁有权访问远程,都可以访问所有的东西,如资源,服务,使用意图等

您可以通过不同的方法获取上下文

  • getApplicationContext()
  • getContext()
  • getBaseContext()
  • 要么 this (在活动课上时)

例:

TextView TV=new TextView(this);

this  - >指当前活动的上下文。


410
2017-08-20 05:25



好的,所以派生自Activity的类本身就是一个上下文。这就是为什么通过将其传递给新创建的视图,我们传递上下文。 - Oleg
我想知道从很多不同的地方获取上下文是否是一个很好的设计决策?在我看来,应用程序中的一个静态getContext()就足够了。 - Trilarion
@Trilarion ...这取决于你想如何使用上下文 getApplicationContext(), getContext(),getBaseContext() .....参考这个 - >(stackoverflow.com/a/10641257) - Devrath
只是为了扩展最后一块创建文本视图:在某些情况下可能需要调用 SomeActivityName.this。在一个实例的线程中, this 是指线程,而不是活动 - Zoe


资源


Android中的Context主题似乎让很多人感到困惑。人们只知道在Android中做基本的事情经常需要Context。人们有时会感到恐慌,因为他们试图执行一些需要上下文的操作,他们不知道如何“获得”正确的上下文。我将尝试揭开Android中Context的神秘面纱。对该问题的完整处理超出了本文的范围,但我将尝试给出一般概述,以便您了解Context是什么以及如何使用它。要了解Context是什么,让我们来看看源代码:

https://github.com/android/platform_frameworks_base/blob/master/core/java/android/content/Context.java

什么是上下文? 

好吧,文档本身提供了一个相当简单的解释:Context类是“关于应用程序环境的全局信息的接口”。

Context类本身被声明为抽象类,其实现由Android OS提供。该文档进一步规定Context“...允许访问特定于应用程序的资源和类,以及对应用程序级操作的上调,例如启动活动,广播和接收意图等”。

你现在可以理解为什么这个名字是Context。这是因为就是这样。 Context(如果您愿意)为活动,服务或任何其他组件提供链接或挂钩,从而将其链接到系统,从而允许访问全局应用程序环境。 换句话说:上下文提供了组件问题的答案:“我到底与app有什么关系?我如何访问/与应用程序的其余部分进行通信?”如果这一切看起来有点令人困惑,请快速查看Context类公开的方法提供了一些关于其真实性质的进一步线索。

以下是这些方法的随机抽样:

  1. getAssets() 
  2. getResources()
  3. getPackageManager()
  4. getString()
  5. getSharedPrefsFile()

所有这些方法有什么共同之处?它们都允许有权访问Context的任何人能够访问应用程序范围的资源。

换句话说,上下文将具有对它的引用的组件挂钩到应用程序环境的其余部分。例如,资产(例如项目中的'/ assets'文件夹)可在整个应用程序中使用,前提是活动,服务或其他任何知道如何访问这些资源的人。 同样的 getResources() 这允许做的事情 getResources().getColor() 这将把你挂进 colors.xml 资源(没关系,aapt允许通过java代码访问资源,这是一个单独的问题)。

结果就是这样 Context 是什么使得能够访问系统资源及其将组件挂钩到“更大的应用程序”。 我们来看看它的子类 Context,提供抽象实现的类 Context 类。 最明显的类是 Activity 类。 Activity继承自 ContextThemeWrapper,继承自 ContextWrapper,继承自 Context 本身。 这些类对于在更深层次上理解事物很有用,但是现在知道它就足够了 ContextThemeWrapper 和 ContextWrapper 几乎就是他们听起来的样子。 他们实现了抽象元素 Context 类本身通过“包装”上下文(实际上下文)并将这些函数委托给该上下文。  一个例子是有用的 - 在 ContextWrapper 类,抽象方法 getAssets 来自 Context class实现如下:

@Override
    public AssetManager getAssets() {
        return mBase.getAssets();
    }

mBase 只是由构造函数设置为特定上下文的字段。 所以上下文被包装了 ContextWrapper 将其getAssets方法的实现委托给该上下文。让我们回过头去看看 Activity 最终继承自的类 Context 看看这一切是如何运作的。

您可能知道什么是活动,但要审查 - 它基本上是“用户可以做的一件事”。它负责提供一个窗口,用于放置用户与之交互的UI。 熟悉其他API甚至非开发人员的开发人员可能会将其本身视为“屏幕”。这在技术上是不准确的,但对我们的目的而言并不重要。怎么做 Activity 和 Context 互动以及他们继承关系到底发生了什么?

同样,查看具体示例也很有帮助。我们都知道如何发起活动。如果你有“上下文”,你正在开始这项活动,你只需打电话 startActivity(intent),Intent描述了您启动Activity的上下文以及您想要启动的Activity。这是熟悉的 startActivity(this, SomeOtherActivity.class)

是什么 thisthis 是你的活动,因为 Activity class继承自 Context。完整的独家新闻是这样的:当你打电话 startActivity,最终 Activity class执行这样的事情:

Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode);

所以它利用了 execStartActivity 来自 Instrumentation class(实际上来自于一个内部类 Instrumentation 叫 ActivityResult)。

在这一点上,我们开始看到系统内部。

这是操作系统实际处理一切的地方。那么Instrumentation如何准确地启动Activity呢?好吧,这个参数 this 在里面 execStartActivity 上面的方法是你的Activity,即Context,和 execStartActivity 利用这个背景。

这是一个30,000概述:Instrumentation类跟踪它正在监视的活动列表,以便完成它的工作。此列表用于协调所有活动,并确保在管理活动流程时一切顺利进行。

有些操作我还没有完全了解哪个坐标线程和进程问题。最终, ActivityResult 使用本机操作 - ActivityManagerNative.getDefault().startActivity() 它使用的 Context 你打电话时传来的 startActivity。您传入的上下文用于在需要时协助“意图解决”。意图解析是系统可以确定意图目标的过程(如果未提供意图)。 (有关详细信息,请查看此处的指南)。

并且为了让Android执行此操作,它需要访问由提供的信息 Context。具体来说,系统需要访问a ContentResolver 所以它可以“确定意图数据的MIME类型”。 这一点关于如何 startActivity 利用上下文有点复杂,我自己并不完全理解内部。我的主要观点是说明如何访问应用程序范围的资源以执行对应用程序至关重要的许多操作。 Context 提供对这些资源的访问。  一个更简单的例子可能是Views。我们都知道您通过扩展创建自定义视图 RelativeLayout 或其他一些 View class,你必须提供一个带有的构造函数 Context 作为一个论点。实例化自定义视图时,您将传递上下文。  为什么?因为View需要能够访问主题,资源和其他View配置详细信息。 查看配置实际上是一个很好的例子。每个上下文都有各种参数(字段在 Context由OS本身设置的实现,如显示的尺寸或密度。很容易理解为什么这些信息对于设置视图等非常重要。

最后一句话:  出于某些原因,刚开始使用Android的人(甚至是不那么新的人)似乎完全忘记了面向对象的编程。出于某种原因,人们试图将他们的Android开发转变为预先设想的范例或学习行为。

Android拥有它自己的范例和某种模式,如果放弃你预先设想的概念并简单阅读文档和开发指南,它实际上是非常一致的。然而,我的真实观点是,虽然“获得正确的背景”有时候会很棘手,但人们会因为遇到需要上下文并认为没有上下文的情况而无理恐慌。 Java是一种面向对象的语言,具有继承设计。

您只有“拥有”Activity内部的上下文,因为您的活动本身继承自Context。它没有什么神奇之处(除了操作系统自己设置各种参数和正确“配置”你的上下文)所做的所有事情。因此,将内存/性能问题放在一边(例如,当您不需要或以对内存产生负面影响的方式执行上下文时保持对上下文的引用等),Context就像任何其他对象一样,它可以传递给它就像任何POJO(Plain Old Java Object)一样。 有时您可能需要做一些聪明的事情来检索该上下文,但是除了Object本身之外的任何其他常规Java类都可以以可访问上下文的方式编写;简单地公开一个带有上下文的公共方法,然后根据需要在该类中使用它。这不是对Context或Android内部的详尽处理,但我希望它有助于揭示Context的一点点。


258
2018-04-30 13:44



这是一个很好的答案。比接受的更好,只能说出每个人都直观的知识。 - Honza Kalfus
这是你正在寻找的答案很长!很好解释 - Nick Jian
优秀的ans!说真的! - ZeekHuge
嗯,对我而言,听起来就像我们的老定时器用来调用全局变量一样,当面向对象进入场景时,这很令人不悦8-) - Ulf Edholm
这应该是公认的答案。 - AymenDaoudi


Context是系统的句柄;它提供诸如解析资源,获取对数据库和首选项的访问等服务。 Context类似于当前运行应用程序的环境的句柄。活动对象继承Context对象。

有关更多信息,请查看 使用Android Studio进行Android开发简介 - 教程


100
2017-08-26 06:33



链接的内容似乎已经改变。尝试章节“5.8。上下文”。但那里的信息不多。 - avenmore
我写这个答案已经2年了。它已移至第5.4节。更新了我的回答以反映.. - giulio
我认为现在是7.4。如果没有最小字符,我会编辑答案。 - ecbrodie
随着Android的新版本问世,新功能等,谷歌将推出doco。感谢更新。 - giulio
“Android应用程序有活动” - 此行不适合您的答案。 - Abhishek Jain


只要你想要思考,就要想大。

有关应用程序环境的全局信息的接口。这是一个抽象类,其实现由Android系统提供。

它允许访问特定于应用程序的资源和类,以及对应用程序级操作的上调,例如启动活动,广播和接收意图等。

Activity diagram


65
2017-12-28 08:05



您能否解释一下图表或分享一些解释相同的资源。 - Prateek
问题已经回答了。下图的思想是表明Context类是导致Activity类的大层次结构的起点。 - Dmytro Danylyk
我同意@Prateek,虽然我可以从图中推断出一些东西,没有任何参考或进一步的解释,这个图只能帮助那些已经清楚地理解了什么的人 Context 是。 - Mike Williamson
好吧,作为一分钟前不理解他们的人,这真的帮助了我。 - Behrooz
这是一个误导性的答案。 Context不仅仅是Activity的祖先,还有很多东西。除了你完全没有解释Context实际上是什么的事实之外,这个'答案'至多完成了25%,因为你忘记了服务和应用程序,它们也是Context-es - Tim Castelijns


安卓和背景

如果您查看各种Android API,您将会 注意到他们中的许多人需要 android.content.Context 对象作为 参数。您还会看到活动或服务通常用作 语境。这是有效的,因为这两个类都从Context扩展。

什么是上下文?

根据Android参考文档,它是一个 表示各种环境数据的实体。它提供访问本地 文件,数据库,与环境关联的类加载器,包括系统级服务在内的服务等。在整本书中,以及在你的日常工作中 使用Android进行日编码,您会看到Context经常传递。 来自:“Android in Practice”一书。


57
2018-04-28 10:14





一个Android 上下文 是一个 接口 允许访问特定于应用程序的资源以及有关应用程序环境的类和信息。

如果您的Android应用程序是一个Web应用程序,   你的背景会是什么   类似于ServletContext(我这里没有做一个精确的比较)

您的活动和服务还会将Context扩展为继承所有这些方法以访问运行应用程序的环境信息。


36
2017-08-26 06:40



AS for Android 4.1 Context是一个抽象类,它提供了访问应用程序环境的各种方法。 - Rakesh
从API级别1开始,Context是一个抽象类,不是4.1 - Sankar V
这是一个抽象的课程...... - Luis Pena
人们,当我引用“界面”时我并不是指java界面,而是 接口 一般意义上讲。 - naikus
显然,一些新手只是不明白什么是“界面”。他们只是认为它是一个java接口。作为参考,我添加了一个链接。在你投票之前请先想想 - naikus


简单的例子来理解 context 在android中:

每个老板都有一个助手照顾,做所有不那么重要和耗时的任务。如果需要一个文件或一杯咖啡,助手就在运行中。有些老板几乎不知道办公室里发生了什么,所以他们也会问他们的助手。他们自己做一些工作,但对于大多数其他事情,他们需要助手的帮助。

在这种情况下,

老板 - 是Android应用程序

助理 - 是背景

文件/一杯咖啡 - 是资源

当我们需要获取有关应用程序的不同部分的信息时,我们通常会调用上下文,如活动,应用程

涉及上下文的一些操作(需要助手的操​​作):

加载公共资源 创建动态视图 显示Toast消息 发起活动等 获取上下文的不同方式:

getContext()

getBaseContext()

getApplicationContext()

this

26
2018-05-02 12:37





  • Context表示获取环境数据的句柄。
  • Context类本身被声明为abstract,其实现由android OS提供。
  • 上下文就像电视中的遥控器和电视中的频道一样是资源,服务等。 enter image description here

你能用它做什么?

  • 加载资源。
  • 发起一项新活动。
  • 创建视图。
  • 获得系统服务。

获取背景的方法:

  • getApplicationContext()
  • getContext()
  • getBaseContext()enter image description hereenter image description here

16
2018-05-02 10:27