Android中关于Context的三言两语,源码强势分析带你了解Context!

前言

==

今天我们来分析一下 Context 的源码,在 APP 开发中,我们会经常用到 Context ,那么什么是 Context 呢?它的常规语义是“上下文”那么这个“上下文”到底是什么呢?通过源码分析,我们能对这个Context有个基本的认识。

类继承图

我们来看下关于 Context 的类继承图,我们通过查看源码得知,Context 是一个抽象类,所以它肯定有其实现类,查阅得知它的实现类为 ContextWrapper 和 ContextImpl ,所以它的继承图如下:

以上的 Context 类继承关系清晰简洁,可以得知,Application 、 Service 、Activity 都是继承的 Context 类,所以从这里我们可以得知:

Context 数量 = Activity 数量 + Service 数量 + 1

另外,我们可以看到 Application 和 Service 都是直接继承 ContextWrapper 的而 Activity 却是继承 ContextThemeWrapper 的,这是为何?其实 ContextThemeWrapper 是关于主题类的,Activity 是有界面的,而 Application 和 Service 却没有。接下来我们来详细看下它们的源码实现。

ContextWrapper

我们进入到 ContextWrapper 源码中可以发现,它其实调用了 mBase 里面的方法,而 mBase 其实是 ContextImpl ,所以最终还是得调用它的实现类 ContextImpl 类里面的方法。

public class ContextWrapper extends Context {

Context mBase;

public ContextWrapper(Context base) {

mBase = base;

}

protected void attachBaseContext(Context base) {

if (mBase != null) {

throw new IllegalStateException(“Base context already set”);

}

mBase = base;

}

//其余的都是覆盖Context里面的方法

}

我们可以按照上面的类的继承图进行依次分析,由上面可以知道 ContextWrapper 其实是调用 ContextImpl 里面的方法,所以 Application 和 Service 还有 Activity 它们应该都跟 ContextImpl 有关的。到底是不是这样的呢?我们追踪源码进行分析。

Application

类似于 Java 的 main 启动方法程序,Android 也有一个类似的方法,那就是在 ActivityThread 类中也有一个 main ,这是开始的地方,我们从这里进行一点一点跟踪:

ActivityThread#main

//省略部分代码…

Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();

thread.attach(false);

//省略部分代码…

Looper.loop();

//省略部分代码…

我们找到 ActivityThread 的 main 方法,省略无关代码,这个 main 方法就是不断的从消息队列中获取消息,然后进行处理。我们本次不分析 Looper 相关的东西,只分析跟 Context 有关的内容,继续进入 attach 方法,

Android 分析源码,不能一头扎进去,我们应该主要分析它的流程。

ActivityThread#attach

//省略部分代码…

mInstrumentation = new Instrumentation();

ContextImpl context = ContextImpl.createAppContext(

this, getSystemContext().mPackageInfo);

//Application的实例创建

mInitialApplication = context.mPackageInfo.makeApplication(true, null);

//调用Application里面的生命周期方法onCreate

mInitialApplication.onCreate();

//省略部分代码…

这里面出现了 ContextImpl ,所以下面应该会跟 Application 扯上关系,所以进入到 makeApplication 方法中继续往下追踪,

LoadedApk#makeApplication

//省略部分代码…

Application app = null;

ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);

app = mActivityThread.mInstrumentation.newApplication(

cl, appClass, appContext);

appContext.setOuterContext(app);

//省略部分代码…

最终又进入到 Instrumentation#newApplication 方法里面

Instrumentation#newApplication

static public Application newApplication(Class<?> clazz, Context context)

throws InstantiationException, IllegalAccessException,

ClassNotFoundException {

Application app = (Application)clazz.newInstance();

app.attach(context);

return app;

}

Application#attach

/**

  • @hide

*/

/* package */

final void attach(Context context) {

attachBaseContext(context);

mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;

}

走到这里就很明清晰了,最终将会调用 ContextWrapper 的 attachBaseContext 方法。从上面到这里,如预料的一样,分析到这里,记住了多少?是不是只知道 Application 里面最终会调用 attachBaseContext 这个方法?这样的话就对了,不能一头扎进代码的海洋里,到处遨游,那样会迷失方向的,Android 源码那么大,那么多,一一细节分析根本是不大可能的,所以只能把握流程,然后再针对性的分析实现过程。接着分析 Service 里面相关的方法。

Service

对于 Service ,我们在 ActivityThread 中可以发现有个方法叫 handleCreateService ,这里面有关于 Service 和 ContextImpl 之间的联系。

ActivityThread#handleCreateService

Service service = null;

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

对于 Application 的那段代码我们可以发现,这两者及其类似,我们进入到 attach 方法中查看相关代码,发现

/**

  • @hide

*/

public final void attach(

Context context,

ActivityThread thread, String className, IBinder token,

Application application, Object activityManager) {

//调用attachBaseContext方法

attachBaseContext(context);

mThread = thread; // NOTE: unused - remove?

mClassName = className;

mToken = token;

mApplication = application;

mActivityManager = (IActivityManager)activityManager;

mStartCompatibility = getApplicationInfo().targetSdkVersion

< Build.VERSION_CODES.ECLAIR;

}

代码很简单,就是这样跟 ContextImpl 扯上关系的。因为 Service 和 Application 都是继承的 ContextWrapper 类,接下来我们来分析一下关于 Activity 的代码。

Activity

在这里说明一下为什么 Service 和 Application 都是继承的 ContextWrapper 类而 Activity 却是继承 ContextThemeWrapper 那是因为 Activity 是带有界面显示的,而 Service 和 Application 却没有,所以从名字我们可以看到 ContextThemeWrapper 包含主题的信息,同时 ContextThemeWrapper 却又是继承自 ContextWrapper ,分析 ContextThemeWrapper 源码我们可以看到,里面基本都是关于 theme 的方法,同时它也覆盖了 attachBaseContext 方法。

我们进入 Activity 源码也发现它也有和 Service 类似的 attach 方法

final void attach(Context context, ActivityThread aThread,

Instrumentation instr, IBinder token, int ident,

Application application, Intent intent, ActivityInfo info,

CharSequence title, Activity parent, String id,

NonConfigurationInstances lastNonConfigurationInstances,

Configuration config, String referrer, IVoiceInteractor voiceInteractor,

Window window, ActivityConfigCallback activityConfigCallback) {

//省略部分代码…

attachBaseContext(context);

接下来我们来分析一下 Activity 在哪里和这个扯上关系的。

ActivityThread#performLaunchActivity

performLaunchActivity 这个方法其实就是启动 Activity 的方法 ,我们以后再来学习关于这个方法的内容,现在先分析 Context 的内容。我们进入到这个方法查看:

//省略部分代码…

ContextImpl appContext = createBaseContextForActivity®;

Activity activity = null;

//省略部分代码…

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

//省略部分代码…

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

尾声

面试成功其实都是必然发生的事情,因为在此之前我做足了充分的准备工作,不单单是纯粹的刷题,更多的还会去刷一些Android核心架构进阶知识点,比如:JVM、高并发、多线程、缓存、热修复设计、插件化框架解读、组件化框架设计、图片加载框架、网络、设计模式、设计思想与代码质量优化、程序性能优化、开发效率优化、设计模式、负载均衡、算法、数据结构、高级UI晋升、Framework内核解析、Android组件内核等。

不仅有学习文档,视频+笔记提高学习效率,还能稳固你的知识,形成良好的系统的知识体系。这里,笔者分享一份从架构哲学的层面来剖析的视频及资料分享给大家梳理了多年的架构经验,筹备近6个月最新录制的,相信这份视频能给你带来不一样的启发、收获。

Android进阶学习资料库

一共十个专题,包括了Android进阶所有学习资料,Android进阶视频,Flutter,java基础,kotlin,NDK模块,计算机网络,数据结构与算法,微信小程序,面试题解析,framework源码!

image

大厂面试真题

PS:之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

《2017-2021字节跳动Android面试历年真题解析》

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

mework源码!

[外链图片转存中…(img-vBXgHKN6-1712209451961)]

大厂面试真题

PS:之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-TSwXLG3m-1712209451962)]

《2017-2021字节跳动Android面试历年真题解析》

[外链图片转存中…(img-zltKg9Z2-1712209451962)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值