引言
Context.getSystemService(String) 方法是我们用来获取各种系统服务的手段,比如:
1 | LayoutInflater LayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); |
BONUS:像这样传入不同的参数(或 String 或 int),返回不同的对象,通常称为『工厂方法』。
那么问题来了:这些服务是从哪里来的呢?
在Android应用的程序入口是哪里?一文中我们知道了,我们App的 Context 的实例实际是 ContextImpl的实例,所以需要去它那边研究。
接下去分析。
深入分析
看看 ContextImpl 的 getSystemService:
1 |
|
发现调用了 SystemServiceRegistry.getSystemService:
1 | // SystemServiceRegistry |
SystemServiceRegistry 是什么?ServiceFetcher又是什么?
当切换到一个新的不熟悉的类的时候,先不要着急,先看看这个类的介绍、结构与方法等,先大致了解一下,再继续深入研究。
SystemServiceRegistry
来看看 SystemServiceRegistry 的定义以及我画的类图:
1 | /** |

可以清楚的看到,SystemServiceRegistry 是『用来管理所有 ContextImpl.getSystemService 所返回的系统服务』的; ServiceFetcher 则是一个泛型接口。
那么是如何管理的呢?
系统服务的注册
在 SystemServiceRegistry 中有一个static块,代码是这样的:
1 | static{ |
我挑了两个例子展示,省略了其他的系统服务注册代码,因为实际上,生成系统服务,就这两种方式:
- 一种是 直接实例化对象,如
PhoneLayoutInflater是直接new出来的。 - 另外一种是从
ServiceManager.getService(String)获取的。
PS:ServiceManager 涉及到了 ServiceManagerNative、Binder、Binder 驱动等相关知识,非常复杂,这里不展开去研究,以后会有机会讲。
原来是在 static 代码块里注册了所有的系统服务。
系统服务的缓存实现
像这种系统服务一般都是大对象,单例,不可能每次获取都是去新建。
所以当然会有缓存啦。
这个缓存在 ContextImpl 中
1 | final Object[] mServiceCache = SystemServiceRegistry.createServiceCache(); |
至于存入缓存的时机,需要看一个 ServiceFetcher 的实现(其他几个原理类似)
1 | // SystemServiceRegistry |
ServiceFetcher.getService 被调用的时候会去判断是否有缓存,如果没有再调用 createService 去创建,再放入缓存,很简单的逻辑。
小结
我们 Context.getSystemService 获取到的系统服务其实从 SystemServiceRegistry 来,它负责注册以及管理系统服务。
推荐阅读
一步一步深入理解CoordinatorLayout
ViewStub是如何实现懒加载的
LayoutInflater源码分析(一)之inflate深度分析
LayoutInflater源码分析(二)之include以及merge标签的处理