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。 |