眼前多少难甘事,自古男儿当自强。这篇文章主要讲述Android Context getSystemService分析相关的知识,希望能为你提供帮助。
我们知道一个应用的Context个数是Activity个数+
Service个数+
1
当我们希望获取到系统服务时,
可以调用Context的getSystemService方法,
如获取到ActivityManager:
ActivityManager manager =
(ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
【Android Context getSystemService分析】那么getSystemService又是怎么工作的呢?
Activity是一个Context, 他调用getSystemService时, 会调用到Context的包装类ContextWrapper的getSystemService方法, 如下:
@
Override
public Object getSystemService(String name) {
return mBase.getSystemService(name);
}
mBase是Context的实现类ContextImpl, 很明显ContextWrapper又会委托ContextImpl去实现具体逻辑。
我们跟进ContextImpl中的getSystemService方法, 如下:
@
Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
其内部是调用了SystemServiceRegistry的getSystemService方法, 这时获取系统服务的过程就转移到了SystemServiceRegistry了。
我们看到SystemServiceRegistry的getSystemService方法即可, 如下:
/**
* Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<
?>
fetcher =
SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher !=
null ? fetcher.getService(ctx) : null;
}
这好像还看不出太多的信息。SYSTEM_SERVICE_FETCHERS.get(name)是什么?
SYSTEM_SERVICE_FETCHERS是一个存储ServiceFetcher的HashMap
private static final HashMap<
String, ServiceFetcher<
?>
>
SYSTEM_SERVICE_FETCHERS =
new HashMap<
String, ServiceFetcher<
?>
>
();
我们先不管SYSTEM_SERVICE_FETCHERS.get(name)返回值是什么,
先发现ServiceFetcher是什么时候存储到SYSTEM_SERVICE_FETCHERS里的。
SystemServiceRegistry中有一段静态代码块长这样:
static {//代码省略registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
new CachedServiceFetcher<
ActivityManager>
() {
@
Override
public ActivityManager createService(ContextImpl ctx) {
return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
}});
registerService(Context.ALARM_SERVICE, AlarmManager.class,
new CachedServiceFetcher<
AlarmManager>
() {
@
Override
public AlarmManager createService(ContextImpl ctx) {
IBinder b =
ServiceManager.getService(Context.ALARM_SERVICE);
IAlarmManager service =
IAlarmManager.Stub.asInterface(b);
return new AlarmManager(service, ctx);
}});
//代码省略
}
静态代码块只在虚拟机第一次加载类的时候执行。
静态代码块中调用registerService方法来注册系统服务的, 而registerService方法内部是将key和value存进去SYSTEM_SERVICE_FETCHERS, 找到了, 如下:
/**
* Statically registers a system service with the context.
* This method must be called during static initialization only.
*/
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);
}
可以看到存进了serviceFetcher, 而serviceName就是我们传进的字符串, 比如
Context.ACTIVITY_SERVICE
我们分析ActivityManager即可, 在注册ActivityManager时传进registerService方法的是CachedServiceFetcher, 那么我们跟进CachedServiceFetcher看看。
/**
* Override this class when the system service constructor needs a
* ContextImpl and should be cached and retained by that context.
*/
static abstract class CachedServiceFetcher<
T>
implements ServiceFetcher<
T>
{
private final int mCacheIndex;
public CachedServiceFetcher() {
mCacheIndex =
sServiceCacheSize+
+
;
}@
Override
@
SuppressWarnings("
unchecked"
)
public final T getService(ContextImpl ctx) {
final Object[] cache =
ctx.mServiceCache;
synchronized (cache) {
// Fetch or create the service.
Object service =
cache[mCacheIndex];
if (service =
=
null) {
service =
createService(ctx);
cache[mCacheIndex] =
service;
}
return (T)service;
}
}public abstract T createService(ContextImpl ctx);
}
CachedServiceFetcher实现了ServiceFetcher接口, 这个getService方法是在一开始的getSystemService方法中触发, 如下
return fetcher !=
null ? fetcher.getService(ctx) : null;
喔, 原来是通过ServiceFetcher来获取系统服务的。
到这里我们分析CachedServiceFetcher可以知道, 当第一次获取服务的时候, 会调用createService去创建实例, 然后将服务对象添加进缓存。下次再取时就直接从缓存中获取了。其实这是一种使用容器来实现的单例模式。
最后总结一下: 当我们调用Context的getSystemService方法获取服务时, 会转到SystemServiceRegistry类的getSystemService方法, 在这个getSystemService方法中, 根据key, 也就是我们传入的字符串, 比如Context.ACTIVITY_SERVICE。根据传入的key从SYSTEM_SERVICE_FETCHERS这个HashMap中获取到ServiceFetcher实例, 再调用ServiceFetcher实例的getService方法获取到系统服务对象。如果是第一次获取系统服务的话, 会调用ServiceFetcher的createService方法去创建系统服务实例并将其加入缓存列表, 之后再次获取就是从缓存中取出了。
而静态代码块又是怎么回事? 其实就是为每一个系统服务执行了以下的代码嘛
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
SystemServiceRegistry中的静态代码块只会执行一次, 告诉系统, 我是有这些服务的, 将一些key和value添加进HashMap。就是一些初始化的工作。而并没有真正去创建系统服务对象, 因为createService还没有被调用啊
好了, 以上就是Context的getSystemService方法的工作过程分析。从中我学到了原来还有这种使用容器的单例模式。
转载请注明出处: http://blog.csdn.net/xyh269
推荐阅读
- Android开发5(应用程序窗口小部件App Widgets的实现)
- Android View的事件分发机制
- Android 升级到android studio 2.2项目死活run不起来
- React Native Android生成已签名的APK
- 勤拂拭软件Android开发之旅 之 Android 开发环境搭建
- 勤拂拭软件系列教程 之 Android开发之旅
- Android Studio 如何添加悬浮提示
- Android聚合广告AFP的对接系统设计
- Android Design Support Library--TextInputLayout的使用