安卓基础Android

Android源码分析-全面理解Context (一)

2022-07-30  本文已影响0人  在岁月中远行

Context在android中的作用不言而喻,当我们访问当前应用的资源时,启动一个新的Activity的时候都需要提供Context,而这个Context到底是什么呢。从字面意思是“上下文”,或者也可以叫做环境,场景等,尽管如此,还是有点抽象,从类的继承来说。Context作为一个抽象的基类,它的实现类有

直接子类有ContextImpl,ContextWrapper,MockContext

ContetxImpl和ContextWrapper是继承Context,但是Context抽象方法是在ContextImpl中实现的,ContextWrapper虽然也继承了Context但是其中的方法实现都是交由ContextImpl去完成的。ContextWrapper只是ContextImpl的包装类。

ContetxThemeWrapper,Service,Application都继承了ContextWrapper,所以它们也可以使用mBase调用Context中的方法,它们也是ContextImpl的包装类。

我们再看ContextWrapper的子类有Application,ReceiverRestrictedContext,Service,ContextThemeWrapper,等等

再看ContextThemeWrapper的子类最重要的Activity。

为什么通过任意的Contxet访问资源所得到的都是同一套资源? getApplication和getApplicationContext有什么区别呢?应用中有多少个Context呢?我们一一来分析下:

什么是Context

Context是一个抽象基类,我们通过它访问当前包的资源(getResources,getAssets)和启动其他组件(Service,Broadcast)以及得到各种服务(getSystemService),当然,通过Context能得到的不仅仅只有这些内容,对Context的理解可以来说:Context提供了一个应用的运行环境,在Context的大环境里,应用才可以访问资源,才能完成和其他组件,服务的交互,Context定义了一套基本的功能接口,我们可以理解为一套规范,这套规范实际是被ContextImpl类统一实现的,Activity和Service只是继承并有选择性地重写了某些规范的实现。

Application,Activity和Service作为Context的区别:

首先看下它们的继承关系:选中Service,按下F4键

Activity的继承关系图:

Application的继承关系图:

通过对比可以清晰地发现,Service和Application的类继承关系比较像,而Service和Application还多了一层继承ContextThemeWrapper,这是因为Activity有主题的概念,而Service是没有界面的服务,Application更是一个抽象的东西。

Context的真正实现类都在ContextImpl中,也就是说Context的大部分实现方法调用都会跳转到ContextImpl中,而Service和Application,Activity三者的创建均在ActivityThread中完成,从Activity的启动流程可以了解到,Activity的启动核心过程是在ActivityThread中完成的,这里说明的是,Application和Service的创建也是在ActivityThread中完成的,下面我们来看看三者在创建时是怎么和ContextImpl相关联的。

ActivityThread中的performLaunchActivity方法

可以看出,Activity在创建的之前会new一个ContextImpl对象并在attach方法中关联它。

下面继续看Application对象中ContextImpl的创建:

我们一般通过getApplicationContext来获取系统全局的Application Context,那么Application Context是在哪里创建的呢?

这就要从应用的启动开始,APP启动会调用ActivityThread的内部类ApplicationThread的scheduleLaunchActivity方法来启动

在ApplicationThread的scheduleLaunchActivity方法中向H类发生LAUNCH_ACTIVITY类型的消息,目的是将启动Activity的逻辑放在主线程的消息队列中,这样启动Activity的逻辑会在主线程中执行,在handleMessage()中调用ActivityThread#handleLaunchActivity()

这个又会调用ActivityThread#performLaunchActivity()

会继续调用LoadedApk#makeApplication

分析1语句 创建ContextImpl的对象,其内部之间通过new ContextImpl()进行创建

分析2语句 通过Instrumention的newApplication()创建Application。

分析3语句 将刚创建的Application类型app赋值给LoadedApk类中的成员变量mAppliction,getApplicationContext方法返回就是这个mApplication。

接下来继续分析Instrumention#newApplication()方法

继续看是 getFactory(context.getPackageName()).instantiateApplication(cl, className);去生成Application

可以看到最终是通过反射创建的,再回过头来看Instrumention.newApplication(),在Application创建完成后调用了Application的attach()

继续看Application的attach方法

里面又调用了父类ContextWrapper的attachBaseContext(context)方法,

这样就把刚创建的ContextImpl对象赋值给了ContextWrapper中的mBase。

上一篇下一篇

猜你喜欢

热点阅读