协慌网

登录 贡献 社区

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

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

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

答案

简单地说:

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

您可以通过调用getApplicationContext()getContext()getBaseContext()this (在从Context扩展的类中,例如 Application,Activity,Service 和 IntentService 类)来获取Context

上下文的典型用法:

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

    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, ...);

Context 的定义::

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

更简单的术语::

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

  • 公司中有一位首席架构师,这位首席架构师负责公司的所有工作,包括数据库,UI 等。

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

  • 建筑师根据新人的技能告诉新雇员的责任,他是否会在数据库或用户界面等方面工作。

更简单的术语::

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

  • 这与你去酒店时的情况类似,你想要在适当的时间吃早餐,午餐和晚餐,对吧?

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

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

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


涉及背景的事情是:

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

Context 是ActivityServiceApplication等的基类

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

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

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

  • getApplicationContext()
  • getContext()
  • getBaseContext()
  • 或者this (在活动课上)

例:

TextView TV=new TextView(this);

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

资源


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本身。这些类对于更深入地理解事物很有用,但是现在知道ContextThemeWrapperContextWrapper几乎就是它们就足够了它们通过 “包装” 上下文(实际上下文)并将这些函数委托给该上下文来实现Context类本身的抽象元素。一个例子很有用 - 在ContextWrapper类中, Context类中的抽象方法getAssets实施如下:

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

mBase只是构造函数设置为特定上下文的字段。因此,上下文被包装, ContextWrapper将其 getAssets 方法的实现委托给该上下文。让我们回过头来检查最终继承自ContextActivity类,看看这一切是如何工作的。

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

同样,查看具体示例也很有帮助。我们都知道如何发起活动。如果你有启动 Activity 的 “上下文”,你只需调用startActivity(intent) ,其中 Intent 描述了启动 Activity 的上下文和你想要启动的 Activity。这是熟悉的startActivity(this, SomeOtherActivity.class)

什么是thisthis是您的 Activity,因为Activity类继承自Context 。完整的独家新闻是这样的:当你调用startActivity ,最终Activity类执行如下所示的事情:

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

因此它使用Instrumentation类中的execStartActivity (实际上来自Instrumentation名为ActivityResult的内部类)。

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

这是操作系统实际处理一切的地方。那么 Instrumentation 如何准确地启动 Activity 呢?那么,帕拉姆thisexecStartActivity上述方法是你的活动,即上下文和execStartActivity利用这个上下文。

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

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

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

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

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

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