Android Context getSystemService分析

Posted yinhuanxu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Context getSystemService分析相关的知识,希望对你有一定的参考价值。

我们知道一个应用的Context个数是Activity个数+Service个数+1

当我们希望获取到系统服务时,可以调用Context的getSystemService方法,如获取到ActivityManager:

ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

那么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 Context getSystemService分析的主要内容,如果未能解决你的问题,请参考以下文章

测试实体框架查找方法

ViewPager切换动画效果改动

如何在Android中获取语言列表

Android如何给通知channel静音

位置返回始终为空 - android

Android如何给通知channel静音