曾经被问过一个问题:Android系统中的Context有几种?当时没怎么说清楚,现在再来聊聊这个问题。
Context是个抽象类,它有两个直接子类:ContextImpl和ContextWrapper。ContextImpl实现了Context中的所有抽象方法,ContextWrapper也实现了Context的抽象方法,但它的实现方式是通过调用其持有的ContextImpl实例mBase的对应的方法,所以它叫做Wrapper,可以理解成ContextImpl的包装类。
1 2 3 Context |--ContextImpl |--ContextWrapper 
而Application、Service都是ContextWrapper的直接子类。此外,ContextWrapper还有其他直接子类,如ContextThemeWrapper、ReceiverRestrictedContext,而Activity则是ContextThemeWrapper的直接子类,因为它需要主题。ReceiverRestrictedContext则是给BroadcastReceiver使用的,后面说。
1 2 3 4 5 6 7 8 Context |--ContextImpl |--ContextWrapper    |--Appliction    |--Service    |--ReceiverRestrictedContext    |--ContextThemeWrapper       |--Activity 
这几个类的实例都是在ActivityThread中创建,其中的Context也是在这里面赋值的,分别来看一看
Activity 创建Activity时,最终会走到ActivityThread.performLauncherActivity方法里
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 private  Activity performLaunchActivity (ActivityClientRecord r, Intent customIntent)           ContextImpl appContext = createBaseContextForActivity(r);          Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);          Application app = r.packageInfo.makeApplication(false , mInstrumentation);          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, r.assistToken);          if  (r.isPersistable()) {         mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);     } else  {         mInstrumentation.callActivityOnCreate(activity, r.state);     } } private  ContextImpl createBaseContextForActivity (ActivityClientRecord r)  	ContextImpl appContext = ContextImpl.createActivityContext(this , r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig); 	return  appContext; } 
可以看到,创建一个Activity的过程主要有3步:一是通过反射创建Activity实例,二是准备相关的参数,其中包含ContextImpl实例和Application实例,接着是attach,在这个方法里初始化Activity的成员变量,其中有一个Application类型的变量mApplication,传入的Application是为了初始化这个变量。
Service 创建Service最终会走到ActivityThread.handleCreateService方法里
1 2 3 4 5 6 7 8 9 10 11 12 13 private  void  handleCreateService (CreateServiceData data)  	 	ContextImpl context = ContextImpl.createAppContext(this , packageInfo); 	 	Application app = packageInfo.makeApplication(false , mInstrumentation); 	 	Service service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent); 	 	service.attach(context, this , data.info.name, data.token, app, ActivityManager.getService()); 	 	service.onCreate(); } 
和Activity类似,不再赘述。
BroadcastReceiver 创建BroadcastReceiver最终会走到ActivityThread.handleReceiver方法里
1 2 3 4 5 6 7 8 9 10 11 private  void  handleReceiver (ReceiverData data)  	 	Application app = packageInfo.makeApplication(false , mInstrumentation); 	 	ContextImpl context = (ContextImpl) app.getBaseContext(); 	 	BroadcastReceiver receiver = packageInfo.getAppFactory().instantiateReceiver(cl, data.info.name, data.intent); 	 	receiver.onReceive(context.getReceiverRestrictedContext(), data.intent); } 
可以看到,BroadcastReceiver没有直接使用创建的ContextImpl,而是通过context.getReceiverRestrictedContext()获取了ReceiverRestrictedContext,上面提过,它是ContextWrapper的直接子类,重写了其中的registerReceiver和bindService方法,方法里直接抛出异常,所以用BroadcastReceiver中的Context无法创建广播和服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class  ReceiverRestrictedContext  extends  ContextWrapper  	@Override      public  Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)           if  (receiver == null ) {                                       return  super .registerReceiver(null , filter, broadcastPermission, scheduler);         } else  {             throw  new  ReceiverCallNotAllowedException("BroadcastReceiver components are not allowed to register to receive intents" );         }     }     @Override      public  boolean  bindService (Intent service, ServiceConnection conn, int  flags)           throw  new  ReceiverCallNotAllowedException("BroadcastReceiver components are not allowed to bind to services" );     } } 
Application 在创建上面3个的时候可以看到,Application都是通过packageInfo.makeApplication来创建的,packageInfo是个类型为LoadedApk类型的实例,具体看一看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public  Application makeApplication (boolean  forceDefaultAppClass, Instrumentation instrumentation)  	if  (mApplication != null ) { 		return  mApplication;      }      ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this );      app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);      mApplication = app;            instrumentation.callApplicationOnCreate(app); } public  Application newApplication (ClassLoader cl, String className, Context context)  throws  InstantiationException, IllegalAccessException, ClassNotFoundException     Application app = getFactory(context.getPackageName()).instantiateApplication(cl, className);     app.attach(context);     return  app; } 
先创建了ContextImpl的实例,然后在Instrumentation中通过反射创建了Application实例,接着将上一步创建的ContextImpl实例通过attach方法传入,最后调用Application.onCreate方法
ContentProvider 四大组件说了三个,再说说最后一个ContentProvicer,虽然不是Context的子类,但也和Context相关。创建Provider在ActivityThread.installProvider方法中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private  ContentProviderHolder installProvider (Context context, ContentProviderHolder holder, ProviderInfo info, boolean  noisy, boolean  noReleaseNeeded, boolean  stable)  	Context c = null ;     ApplicationInfo ai = info.applicationInfo;     if  (context.getPackageName().equals(ai.packageName)) {         c = context;     } else  if  (mInitialApplication != null  && mInitialApplication.getPackageName().equals(ai.packageName)) {         c = mInitialApplication;     } else  {         try  {             c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE);         } catch  (PackageManager.NameNotFoundException e) {      }      	ContentProvider localProvider = packageInfo.getAppFactory().instantiateProvider(cl, info.name); 	localProvider.attachInfo(c, info); } 
视情况而定,ContextImpl的来源有多种,但最后都是通过attachInfo方法传入ContentProvider。
总结 回到最初的问题,Context有几种呢,就普遍性而言有3种:Application、Activity和Service,如果严谨一点,算上ReceiverRestrictedContext的话,那么就是4种。