Android Context 到底是什么

Android Context 到底是什么

Context 到底是什么?
如果面试官问这样一个问题,你该如何回答呢?
这里希望通过这篇文章,梳理一下,然后给自己一个**Context 到底是什么?**的解答。

官方API

谷歌官方API上这样写道:

Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.

来自:
https://developer.android.com/reference/android/content/Context

翻译一下:
Context是一个关于application environment(应用环境)的全局信息入口。Context是一个抽象类,由Android系统提供Context的实现。Context允许访问应用程序特定的资源和类,以及调用应用程序级操作,如启动activity、发送广播、接收 intent 等

这么看Context是:
一个关于App的全局信息入口。Context的作用是访问应用资源和类、启动Activity、发送广播、接收 intent 等。

Context 一个关于App的全局信息入口

Context既然是一个抽象类,那我们就来看一下它的实现子类。
Android源码(android-25)中,它的子类关系图如下:

Android Context 到底是什么_第1张图片

通过查看源码,我们得知:

  • Context是一个抽象类,类中只有方法定义,并没方法实现;
    Context提供了访问当前包的资源(getResources、getAssets)方法 和 启动其他组件(Activity、Service、Broadcast)以及得到各种服务(getSystemService)的方法;
  • ContextWrapper 不是Context中抽象方法的实现类,只是一个包装类,构造方法中传入了一个context对象;ContextImpl实现了Context中的抽象方法;
  • Context中方法的实现类是ContextImpl,这点通过源码可以看到:
    https://www.androidos.net.cn/android/7.1.1_r28/xref/frameworks/base/core/java/android/app/ContextImpl.java

到这里,觉得:Context就是一个提供App内资源访问的全局信息入口。

网络上说法

看到Context 都没弄明白,还怎么做 Android 开发?中有这么一句话,觉得很有意思,写在这里:

一个Activity就是一个Context,一个Service也是一个Context。
Android程序员把“场景”抽象为Context类,他们认为用户和操作系统的每一次交互都是一个场景,比如打电话、发短信,这些都是一个有界面的场景;还有一些没有界面的场景,比如后台运行的服务(Service)。
一个应用程序可以认为是一个工作环境,用户在这个环境中会切换到不同的场景,这就像一个前台秘书,她可能需要接待客人,可能要打印文件,还可能要接听客户电话,而这些就称之为不同的场景,前台秘书可以称之为一个应用程序。

这里有一个问题

既然Activity、Application、Service 都是一个Context对象,Context可以提供资源的访问。那么如何保证,在Activity、Service中获取到的资源为同一份资源呢?

这里我们先查一下ContextImpl的源码:
源码地址:
https://www.androidos.net.cn/android/7.1.1_r28/xref/frameworks/base/core/java/android/app/ContextImpl.java

@Override
public Resources getResources() {
    return mResources;
}
  • Context中的资源是通过mResources获取的,下边看一下mResources对象的创建。

在ContextImpl构造方法中发现:

private ContextImpl(ContextImpl container, ActivityThread mainThread,
            LoadedApk packageInfo, IBinder activityToken, UserHandle user, int flags,
            Display display, Configuration overrideConfiguration, int createDisplayWithId) {
        mOuterContext = this;
        // 这里省略部分代码...
        // 构造方法中创建了一个ResourcesManager对象
        mResourcesManager = ResourcesManager.getInstance();

        final int displayId = (createDisplayWithId != Display.INVALID_DISPLAY)
                ? createDisplayWithId
                : (display != null) ? display.getDisplayId() : Display.DEFAULT_DISPLAY;

        CompatibilityInfo compatInfo = null;
        if (container != null) {
            compatInfo = container.getDisplayAdjustments(displayId).getCompatibilityInfo();
        }
        if (compatInfo == null) {
            compatInfo = (displayId == Display.DEFAULT_DISPLAY)
                    ? packageInfo.getCompatibilityInfo()
                    : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
        }

        Resources resources = packageInfo.getResources(mainThread);
        if (resources != null) {
            if (displayId != Display.DEFAULT_DISPLAY
                    || overrideConfiguration != null
                    || (compatInfo != null && compatInfo.applicationScale
                            != resources.getCompatibilityInfo().applicationScale)) {

                if (container != null) {
                    // This is a nested Context, so it can't be a base Activity context.
                    // Just create a regular Resources object associated with the Activity.
                    resources = mResourcesManager.getResources(
                            activityToken,
                            packageInfo.getResDir(),
                            packageInfo.getSplitResDirs(),
                            packageInfo.getOverlayDirs(),
                            packageInfo.getApplicationInfo().sharedLibraryFiles,
                            displayId,
                            overrideConfiguration,
                            compatInfo,
                            packageInfo.getClassLoader());
                } else {
                    // This is not a nested Context, so it must be the root Activity context.
                    // All other nested Contexts will inherit the configuration set here.
                    resources = mResourcesManager.createBaseActivityResources(
                            activityToken,
                            packageInfo.getResDir(),
                            packageInfo.getSplitResDirs(),
                            packageInfo.getOverlayDirs(),
                            packageInfo.getApplicationInfo().sharedLibraryFiles,
                            displayId,
                            overrideConfiguration,
                            compatInfo,
                            packageInfo.getClassLoader());
                }
            }
        }
        // ResourcesManager 通过getResources方法创建了Resources对象
        mResources = resources;
        
        // 这里省略部分代码...
    }

通过以上代码,我们得知:

  • ContextImpl构造方法中创建了一个ResourcesManager对象
  • ResourcesManager 通过getResources方法创建了Resources对象,用来获取资源。
//
private static ResourcesManager sResourcesManager;
//
public static ResourcesManager getInstance() {
    synchronized (ResourcesManager.class) {
        if (sResourcesManager == null) {
            sResourcesManager = new ResourcesManager();
        }
        return sResourcesManager;
    }
}

查看ResourcesManager源码,发现ResourcesManager是一个单例,因此Activity、Application、Service通过ResourcesManager获取的资源,为同一资源。

========== THE END ==========

您对“我的文章”有任何疑问,可用微信扫描以下“二维码”向我提问!

在这里插入图片描述

你可能感兴趣的:(Android源码)