一个Context意味着一个场景,一个场景就是咱们和软件进行交互的一个过程。好比当你使用微信的时候,场景包括聊天界面、通信录、朋友圈,以及背后的一些数据。java
那么从程序的角度来看,Context是什么?其实一个Activity就是一个Context,一个Service也是一个Context。微信
一个应用程序能够认为是一个工做环境,用户在这个工做环境中会切换到不一样的场景,这就像一个助理,他可能须要接待客人,可能还要打印文件,还可能接听电话,而这些就称之为不一样的场景,助理可称之为一个应用程序。架构
Activity类的确是基于Context,而Service类也是基于Context。Activity除了基于Context类外,还实现了一些其余重要的接口,从架构设计的角度看,interface仅仅是某些功能,而extends才是类的本质,即Activity的本质是一个Context,其所实现的其余接口只是为了扩充Context的功能而已,扩充后的类称之为一个Activity或Service。app
咱们在应用程序开发中常常会调用Context的一些方法,这些方法看起来彷佛会返回一些全局的对象,而不单单是某个Activity,可能会有点疑问,一个应用程序到底有多少个Context对象呢?好比,Context.getResources()返回该应用程序所对应的Resource类对象,不管从哪一个Activity中调用,都会返回同一个Resource对象。函数
Context类自己是一个纯abstract类。为了使用方便又定义了Context包装类-ContextWrapper,ContextWrapper构造函数中必须包含一个真正的Context引用,同时ContextWrapper中有attachBaseContext()用于给ContextWrapper对象中指定真正的Context对象。this
ContextThemeWrapper内部包含了与主题相关的接口,这里的主题就是指在AndroidManifest.xml中经过Android:theme为Application或者Activity指定的主题。spa
只有Activity才须要主题,Service不须要主题的,因此Service直接继承与ContextWrapper。架构设计
ContextImpl类真正实现了Context中全部的函数,咱们所调用的各类Context类的方法其实实现均来自于该类。设计
每个应用程序在客户端都是从ActivityThread类开始的,建立Context对象也是在该类中完成,具体建立ContextImpl类的地方一共有6处:orm
其中attach()方法仅在Framework进程启动时调用,应用程序运行时不会调用到该方法。
程序第一次启动时,会展转调用到makeApplication()方法。具体代码以下:
ContextImpl appContext = new ContextImpl();
appContext.init(this,null,mActivityThread); .... appContext.setOuterContext(app);
启动Activity时,Ams会经过IPC调用到ActivityThread的scheduleLaunchActivity()方法,该方法包含两种参数。一种是ActivityInfo,这是一个实现了Parcelable接口的数据类,意味着该对象是Ams建立的,并经过IPC传递到ActivityThread;另外一种是其余的一些参数。
scheduleLaunchActivity()方法中会根据以上两种参数构造一个本地ActivityRecord数据类,ActivityThread内部会为每个Activity建立一个ActivityRecord对象,并使用这些数据对象来管理Activity。
而后会调用handleLaunchActivity(),再调用performLaunchActivity(),该方法中建立ContextImpl的代码以下:
ContextImpl appContext = new ContextImpl();
appContext.init(r.packageInfo,r.token,this); appContext.setOuterContext(activity);
在performLaunchActivity()开始执行时,会为r.packageInfo变量赋值。r.packageInfo对象的PackageInfo对象和Application对应的packageInfo对象是同一个。
启动Service时,Ams会经过IPC调用到ActivityThread的scheduleCreateService()方法,该方法也包含两种参数。第一种是ServiceInfo,这是实现了一个Parcelable接口的数据类,该对象由AmS建立,并经过IPC传递到ActivityThread内部;第二种是其余参数。
在scheduleCreateService()方法中,会使用以上两种参数构造一个CreateServiceData的数据对象,ActivityThread会为其所包含的每个Service建立该数据对象,并经过这些对象来管理Service。
而后在执行handleCreateService()方法,建立ContextImpl对象代码以下:
ContextImpl appContext = new ContextImpl();
appContext.init(packageInfo,null,this); ... appContext.setOuterContext(service);
Service对应的Context对象内部的mPackageInfo与Activity、Application中是彻底相同的。
从以上能够看出,建立Context对象的过程基本上是相同的,不一样的仅仅是针对Application、Activity、Service使用了不一样的数据对象。
一个应用程序包含的Context个数应该为:Context个数 = Service个数+Activity个数+1,最后的1是Application类自己也会对应一个Context对象。
应用程序中包含多个ContextImpl对象,而内部变量mPackageInfo却指向同一个PackageInfo对象,这种设计结构通常意味着ContextImpl是一种轻量级类,而PackageInfo是一个重量级类。事实上确实是这样,ContextImpl中的大多数进行包操做的重量级函数实际上都是转向了mPackageInfo对象相应的方法,也就是事实上调用了同一个PackageInfo对象。