从getSystemService()出发获取系统服务

来源:互联网 发布:淘宝申请延长收货时间 编辑:程序博客网 时间:2024/05/16 10:49

(本文的分析基于Android7.0的源码)
开始阅读本文的你一定很好奇,为啥在Activity使用getSystemSerive,传入相应的系统服务名字就可得到相应的系统服务,这其中又是怎么管理系统服务的呢?先不要急,本文将从最基础的入手慢慢为你介绍getSystemService的原理。
我们使用getSystemService最多的地方莫过于在Activity中使用,暂且看看Activity中是怎样实现的。

@Overridepublic Object getSystemService(@ServiceName @NonNull String name) {    if (getBaseContext() == null) {        throw new IllegalStateException(                "System services not available to Activities before onCreate()");    }    if (WINDOW_SERVICE.equals(name)) {        return mWindowManager;    } else if (SEARCH_SERVICE.equals(name)) {        ensureSearchManager();        return mSearchManager;    }    return super.getSystemService(name);}

我们都知道Activity是继承于ContextThemeWrapper,因此上述源码中最后返回的也是ContextThemeWrapper中的getSystemService这个方法的返回值。再来看看ContextThemeWrapper中的这个方法。

@Overridepublic Object getSystemService(String name) {    if (LAYOUT_INFLATER_SERVICE.equals(name)) {        if (mInflater == null) {            mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);        }        return mInflater;    }    return getBaseContext().getSystemService(name);}

可以看到这个方法里先对name进行了判断,我们暂时认为上述name不等于LAYOUT_INFLATER_SERVICE。则这个方法返回的是getBaseContext()的getSystemService方法。那么getBaseConxt()方法是什么呢。它又是一个继承的方法,在ContextThemeWrapper的父类ContextWrapper中就定义了这个方法,它返回的是一个Context对象。我们都知道Context是一个抽象类,它在Android中的具体实现是ContextImpl,因此这里最终调用的是ContextImpl中的getSystemService方法。至于ContextImpl是如何将Context对象传到这里的呢,它的具体实现在ActivityThread的createBaseContextForActivity方法中,这里暂不做阐述。我们先来看看ContextImpl。
它在源码中的路径是: frameworks/base/core/java/android/app/ContextImpl.java
ContextImpl中getSystemService的实现如下:

@Overridepublic Object getSystemService(String name) {    return SystemServiceRegistry.getSystemService(this, name);}

最后又跳转到SystemServiceRegistry这个类的getSystemService方法。到这里不得不佩服一下开发Android系统的工程师,源码里的东西可以用迂回曲折来形容,作为后来学习的人都看晕了,设计者却能保持清醒。废话不多说,我们来看看SystemServiceRegistry这个类。
同样,它也是android.app包下的一个类。在注释中,我们可以看到设计者是这样介绍它的。

Manages all of the system services that can be returned by {@link Context#getSystemService}.

由此可见,我们可以通过getSystemService返回的系统服务都由它来管理。SystemServiceRegistry这个类里借助于静态代码块,当我们使用到这个类时,一系列系统服务就开始在这里被注册。

static {    registerService(Context.WIFI_NAN_SERVICE, WifiNanManager.class,            new StaticServiceFetcher<WifiNanManager>() {    @Override    public WifiNanManager createService() {        IBinder b = ServiceManager.getService(Context.WIFI_NAN_SERVICE);        IWifiNanManager service = IWifiNanManager.Stub.asInterface(b);        if (service == null) {            return null;        }        return new WifiNanManager(service);    }});      ......    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(Context.TELECOM_SERVICE, TelecomManager.class,        new CachedServiceFetcher<TelecomManager>() {        @Override        public TelecomManager createService(ContextImpl ctx) {            return new TelecomManager(ctx.getOuterContext());    }});    ......}

在这里我们可以看到它是通过registerService将一系列服务信息放到HashMap里,然后等待有需要的时候去容器里取。

private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =        new HashMap<Class<?>, String>();private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =        new HashMap<String, ServiceFetcher<?>>();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);}

我们回来看看getSystemService这个方法

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中根据name取出ServiceFetcher对象,最后返回了fetcher.getService(ctx)的返回值。ServiceFetcher也在SystemServiceRegistry中被定义,它是一个抽象接口,其实现类是CachedServiceFetcher、StaticServiceFetcher和StaticApplicationContextServiceFetcher,这里为什么有三个类?从源码的注释可以获得以下信息:
(1) 当我们的系统服务需要ContextImpl并且能被ContextImpl缓存和保留需要用到CachedServiceFetcher
(2) 当我们的系统服务不需要ContextImpl并且在系统进程范围被缓存和保留需要用到StaticServiceFetcher
(3) 每个应用只创建一个服务实例的时候会用到StaticApplicationContextServiceFetcher

这三种ServiceFetcher在上述的静态代码块里已经以匿名内部类的形式注册,最后我们调用的fetcher.getService(ctx)就是从里面获取具体的服务对象。

至此已经把getSystemService获取服务对象的过程简要阐述了一遍。如有错误还望指出。

原创粉丝点击