是什么

从应用场景的角度来说, 他是一个场景, 一个用户与系统交互的过程. 比如当你看短信时, 场景包括短信的页面, 以及隐藏在后面的数据

提到页面, 我们应该能够联想到 Activity

没错,Activity,Service 都是一个 Context

从 JAVA 语言角度来说,Context 是一个抽象类, 抽象类中包含了 Application 环境的一些函数, 设计角度而言,Context 仅提供某些功能, extends 才是类的本质, 即 Activity 的本质是一个 Context , 其所实现的其他接口只是为了扩充 Context 的功能而已, 扩充后的类称之为 Activity 或 Service

有多少 Context

  • Application 一个 Context
  • 多少个 Activity 就有多少个 Context
  • 多少个 Service 就有多少个 Context

Context 个数 =1 + Activity 个数 + Service 个数

Application 的 Context 创建

在博客 ActivityThread.main 过程 中分析中可以知道, handleBindApplication 函数中会调用 makeApplication

makeApplication 会创建 Application 以及创建 ContextImpl

创建 ContextImpl

ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
复制代码

这里的 this 是 LoadedApk 对象, 该对象是在 handleBinderApplication 中赋值

data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
复制代码

在该函数中, 会根据 AppBindData(handleBinderApplication 中的参数) 中的 ApplicationInfo 的 mPackageName 创建一个 PackageInfo 对象并保存为 ActivityThread 类的全局对象

显然, 一个应用程序中所有 Activity 或者 Application 或 Servie, 他们的 mPackageName 是一样的, 即为包名, 因此 ActivityThread 只会有一个全局的 PackageInfo 对象

在 newApplication 的函数中会调用 Application 的 attach

attach

final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }
复制代码

查看 attachBaseContext

protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }
复制代码

这个 mBase 就是 ContextWrapper 中的 Context

Activity 的 Context 创建

Launcher 启动流程 的分析中可以知道,handleLaunchActivity 会调用到 performLaunchActivity, 该函数会调用 createBaseContextForActivity

    private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
        final int displayId;
        ...
        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
        ...
        return appContext;
    }
复制代码

createActivityContext

createActivityContext 中的 packageInfo 信息和上小节分析的流程基本一致, 他也是全局的

static ContextImpl createActivityContext(ActivityThread mainThread,
            LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
            Configuration overrideConfiguration) {
        ...
    ContextImpl context = <span class="hljs-keyword">new</span> ContextImpl(<span class="hljs-keyword">null</span>, mainThread, packageInfo, activityInfo.splitName,
            activityToken, <span class="hljs-keyword">null</span>, <span class="hljs-number">0</span>, classLoader);

    ...
    <span class="hljs-keyword">return</span> context;
}
复制代码

attach

创建 Context 完成后, 调用 activity 的 attach 函数

activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
复制代码

attach 函数中做了很多的赋值操作, 其中 attachBaseContext 的函数和 Application 的 attachBaseContext 中作用一致, 把 context 赋值给 ContextWrapper 的 mBase

:::danger 笔记 因此, 当我们翻阅 Activity 源码, 看到 mBase 时, 就应该去找 ContextImpl 里的方法 :::

Service 的 Context 创建

Service 的启动和 Activity 类似, 最终同样会调用到 ActivityThread 里的函数, 为 scheduleCreateService, 接着调用 handleCreateService

在 handleCreateService 中会创建 Context

ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
service.onCreate();
复制代码

Context 的创建方式和 Application 一致, 同样在创建后会调用 attach 进行一些赋值操作, 同样也有之前分析的 mBase

总结

不同 Context 子类中 PackageInfo 对象来源

类名 远程数据类 本地数据类 赋值方式
Application ApplicationInfo AppBindData getPackageInfoNoCheck
Activity ActivityInfo ActivityClientRecord getPackageInfo
Service ServiceInfo CreateServiceData getPackageInfoNoCheck

参考书籍: Android 内核剖析

  • Android

    开放手机联盟(一个由 30 多家科技公司和手机公司组成的团体)已开发出 Android,Android 是第一个完整、开放、免费的手机平台。

    293 引用
感谢    赞同    分享    收藏    关注    反对    举报    ...