基础
当应用的进程启动时,会得到一个整个应用的context(通过getApplicationContext()得到)。Activity,Service都是Context的子类,所以每一个Activity,Service都是一个Context。
在一般情况下,两者是可以通用的,如toast中需要的context传入两者中的任何一个都行。但在有些时候只能用后者,不能用前者。如上面说的弹出dialog时(因为dialog是activity的一部分)。所以,在以后需要context的时候,尽量使用activity.this,而不使用getApplicationContext()。但是,当打开数据库的时候,如果传入的context是activity.this,那么这个打开的数据库,会随着activity的销毁而关闭;如果传入的是getApplicationContext,就不会有这种情况 。
另外还有在测试单元中,也可以得到一个context,这个context是虚拟的。
Context的子类为ContextImpl。
setOuterContext
该方法是在ActivityThread#createBaseContextForActivity()——它是startActivity()执行的必经一步——中进行调用的,其传入的为一个Activity实例。
因此,Context中可以通过mOuterContext访问到它所关联的Activity实例。同样,在Activity实例中可通过mBase访问到它所关联的Context对象。
getSystemService
经常使用它来获取一些管理类。
对于Context而言,它的实现子类是ContextImpl。ContextImpl中的方法如下:
在静态代码块中,全部是调用registerService(),截取其中一部分如下:
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
SystemServiceRegistry,该类其内部八、九成的代码都在一个静态代码块中,而在ContextImpl有一个成员变量定义如下:
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();//后者只是返回了一个Object[]
因此,在ContextImpl初始化时SystemServiceRegistry就已经加载成功了,静态代码块中的代码也早就执行完毕了。在静态代码块中,全部是调用registerService(),截取其中一部分如下:
registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
new CachedServiceFetcher<LayoutInflater>() {
@Override
public LayoutInflater createService(ContextImpl ctx) {
return new PhoneLayoutInflater(ctx.getOuterContext());
}});
registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
new CachedServiceFetcher<ActivityManager>() {
@Override
public ActivityManager createService(ContextImpl ctx) {
return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
}});
可以看出,该代码块就是注册一堆的Fetcher。看一下registerService()以及相对的get方法如下: public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
public static String getSystemServiceName(Class<?> serviceClass) {
return SYSTEM_SERVICE_NAMES.get(serviceClass);
}
private static <T> void registerService(String serviceName, Class<T> serviceClass,
ServiceFetcher<T> serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
涉及到的两个变量的定义如下: private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
new HashMap<Class<?>, String>();
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
因此,registerService()只是将简单地将往两个Map中添加数据。而get也只是简单地从两个map中取数据。
从上面的分析可以得出:
Context#getSystemService->SystemServiceRegistry#getSystemService()->CachedServiceFetcher#getService.
CachedServiceFetcher如下:
Context#getSystemService->SystemServiceRegistry#getSystemService()->CachedServiceFetcher#getService()->CachedServiceFetcher#createService
Context#getSystemService->SystemServiceRegistry#getSystemService()->CachedServiceFetcher#getService.
CachedServiceFetcher如下:
static abstract interface ServiceFetcher<T> {
T getService(android.app.ContextImpl ctx);
}
static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
private final int mCacheIndex;
public CachedServiceFetcher() {
mCacheIndex = sServiceCacheSize++;
//sServiceCacheSize为静态的全局变量,每new一个CachedServiceFetcher对象时,自动+1,这样就保证了不同的CachedServiceFetcher对象中mCacheIndex是不同的。
}
@Override
@SuppressWarnings("unchecked")
public final T getService(android.app.ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
synchronized (cache) {
Object service = cache[mCacheIndex];
if (service == null) {//第一次调用,该判断肯定成立。
service = createService(ctx);
cache[mCacheIndex] = service;//缓存,下次就不用走createService()了。也就是实现了各种Context#getSystemService()返回值的单例模式。
}
return (T)service;
}
}
public abstract T createService(android.app.ContextImpl ctx);//这个方法,在静态代码中registerService时都实现了
}
因此,可以将上面的调用过程补充完整Context#getSystemService->SystemServiceRegistry#getSystemService()->CachedServiceFetcher#getService()->CachedServiceFetcher#createService
故Context#getSystemService的返回值就是CachedServiceFetcher#createService的返回值。根据自己传入到getSystemService中的值就可以得到对应的Service的实例,而且getSystemService返回的实例都是单例的。例如LayoutInflater的具体实现子类就是PhoneLayoutInflater,WindowManager的具体实现子类为WindowManagerImpl。