「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
在分析源码的时候,经常会看到由很多调用Context的getSystemService函数的例子,其实很简单,本篇记录一下这个函数的调用过程!
mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
首先,调用Context的getSystemService函数,上述函数在初始化WindowManagerService的时候,调用的一个语句,而在WindowManagerService的初始化函数的context参数是从SystemServer中传入的
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
分析过SystemServer启动流程的话,我们应该知道,此处的context参数是通过ActivityThread的getSystemContext函数得到的,而在此前分析的文章SystemServer.createSystemContext函数流程分析中可以知道,此处的getSystemContext函数获取到的是一个ContextImpl对象,因此,此处调用的是ContextImpl的getSystemService函数
public Object getSystemService(String name) {
// ...... 代码暂与本篇无关,省略
// 最终调用的是SystemServiceRegistry的getSystemService函数
return SystemServiceRegistry.getSystemService(this, name);
}
public static Object getSystemService(ContextImpl ctx, String name) {
// ......
// 可以看到,此处是从SYSTEM_SERVICE_FETCHERS中获取name对应的VALUE
final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
// ...... 功能无关代码,省略
// 调用对应的getService函数
final Object ret = fetcher.getService(ctx);
// ...... 功能无关代码,省略
return ret;
}
可以看到,此处有两个步骤
- 从SYSTEM_SERVICE_FETCHERS中获取name对应的VALUE,此处的name为Context.DISPLAY_SERVICE
- 调用获取的对应VALUE值的getService函数
获取ServiceFetcher对象
首先,我们需要分析一下SYSTEM_SERVICE_FETCHERS究竟是什么
private static final Map<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new ArrayMap<String, ServiceFetcher<?>>();
这个对象的定义在SystemServiceRegister类中,且其为static的一个Map容器对象,而对应地SystemServiceRegister.java
static {
// ...... 跟本篇无关代码,省略
registerService(Context.DISPLAY_SERVICE, DisplayManager.class,
new CachedServiceFetcher<DisplayManager>() {
@Override
public DisplayManager createService(ContextImpl ctx) {
return new DisplayManager(ctx.getOuterContext());
}});
// ...... 跟本篇无关代码,省略
}
可以看到,这边会调用registerService函数,而这边注意第三个参数,是一个CachedServiceFetcher对象 如下,查看这个类对象的类图结构
classDiagram
ServiceFetcher <|-- CachedServiceFetcher
class CachedServiceFetcher {
+createService(in ContextImpl ctx) *
+getService(in ContextImpl ctx)
}
<<abstract>> CachedServiceFetcher
<<abstract>> ServiceFetcher
从这个类图中可以看到,此处CachedServiceFetcher类为一个抽象类,其中包含一个抽象函数createService,还有一个函数getService 再继续查看registerService函数
/**
* Statically registers a system service with the context.
* This method must be called during static initialization only.
*/
private static <T> void registerService(@NonNull String serviceName,
@NonNull Class<T> serviceClass, @NonNull ServiceFetcher<T> serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
// 可以看到SYSTEM_SERVICE_FETCHERS中添加的是,传入的名称serviceName和第三个参数ServiceFetcher对象组成的一个键值对
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
SYSTEM_SERVICE_CLASS_NAMES.put(serviceName, serviceClass.getSimpleName());
}
因此,此处名称为Context.DISPLAY_SERVICE对应的VALUE值为传入的第三个参数ServiceFetcher对象
调用对应的getService函数
如上分析可知,此时会调用传入的第三个参数CachedServiceFetcher对象的getService函数 因此
new CachedServiceFetcher<DisplayManager>() {
@Override
public DisplayManager createService(ContextImpl ctx) {
return new DisplayManager(ctx.getOuterContext());
}
}
public final T getService(ContextImpl ctx) {
final Object[] cache = ctx.mServiceCache;
final int[] gates = ctx.mServiceInitializationStateArray;
boolean interrupted = false;
// 传入的T模板是DisplayManager类
T ret = null;
for (;;) {
// for循环中,先将这个值设置为false
boolean doInitialize = false;
synchronized (cache) {
// Return it if we already have a cached instance.
// 第一次肯定没有添加,此处使用这种方式,能够优化调用速度
// 如果已经调用过一次,就直接从这边的cache数组中获取即可
T service = (T) cache[mCacheIndex];
if (service != null || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
ret = service;
break; // exit the for (;;)
}
// ...... 代码暂与本篇无关,省略
// At this point, the gate must be either UNINITIALIZED or INITIALIZING.
// 第一次进入,设置doInitialize的值为true
if (gates[mCacheIndex] == ContextImpl.STATE_UNINITIALIZED) {
doInitialize = true;
gates[mCacheIndex] = ContextImpl.STATE_INITIALIZING;
}
}
if (doInitialize) {
// Only the first thread gets here.
T service = null;
@ServiceInitializationState int newState = ContextImpl.STATE_NOT_FOUND;
try {
// This thread is the first one to get here. Instantiate the service
// *without* the cache lock held.
// 调用createService函数,创建一个T模板DisplayManager对象
service = createService(ctx);
newState = ContextImpl.STATE_READY;
}
// ...... 代码暂与本篇无关,省略
// 返回对应的service
ret = service;
break; // exit the for (;;)
}
// ...... 代码暂与本篇无关,省略
}
// ...... 代码暂与本篇无关,省略
return ret;
}
如上代码可知,当第一次进入这个函数的时候,会直接通过调用其createService函数来创建一个服务对象,若非第一次进入,则直接从对应的数组中获取一个该对象即可
总结
Context的getSystemService函数,在此处最终通过ContextImpl对象的getSystemService函数调用到SystemServiceManager的getSystemService函数
而在SystemServiceManager对象中,其包含有static块,在第一次初始化的时候,会注册所有的Service
当getSystemService函数被调用的时候,会直接从对应的Map集合中获取对应的服务