Android Context getSystemService分析
来源:互联网 发布:市场销售计划软件 编辑:程序博客网 时间:2024/05/18 03:35
我们知道一个应用的Context个数是Activity个数+Service个数+1
当我们希望获取到系统服务时,可以调用Context的getSystemService方法,如获取到ActivityManager:
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
那么getSystemService又是怎么工作的呢?
Activity是一个Context,他调用getSystemService时,会调用到Context的包装类ContextWrapper的getSystemService方法,如下:
@Overridepublic Object getSystemService(String name) { return mBase.getSystemService(name);}
mBase是Context的实现类ContextImpl,很明显ContextWrapper又会委托ContextImpl去实现具体逻辑。
我们跟进ContextImpl中的getSystemService方法,如下:
@Overridepublic 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 Context getSystemService分析
- Android Context getSystemService分析
- Android context.getSystemService()浅析
- Android getSystemService 源码分析
- Context.getSystemService
- android系统getSystemService原理分析
- Android 关于系统Context.getSystemService(String arg0)获取系统服务的详细剖析-getSystemService
- getSystemService(Context.INPUT_METHOD_SERVICE)
- Android getSystemService
- Android getSystemService
- android getSystemService
- Android getSystemService()
- android getSystemService()
- context.getSystemService的简单说明
- ServiceManager.getService和Context.getSystemService
- context.getSystemService(context.LAYOUT_INFLATER_SERVICE)调用时报NullPointerException
- Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
- android--context分析
- 在MFC中,不借用其他的库函数读取BMP图像,显示,也可以重新生成
- HTML第二章上机练习1
- doubango日志
- Logger日志级别说明及设置方法、说明
- iOS开发 jenkins(DRYPlugin)+PMD/CPD 检测重复代码
- Android Context getSystemService分析
- Ubuntu下用eclipse调试caffe code
- android studio编译错误 之 Cause: com/android/builder/profile/Recorder$Property
- GMII,RGMII,SGMII,TBI,RTBI接口信号及时序介绍
- 笔记本内存选择
- 可行性研究
- 网页插入PPT
- c++继承体系中的拷贝控制成员的定义
- 体验活动的生命周期