从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获取服务对象的过程简要阐述了一遍。如有错误还望指出。
- 从getSystemService()出发获取系统服务
- 浅析getSystemService获取系统服务
- 系统服务-----Activity服务的获取getSystemService
- Android getSystemService获取系统相应的服务
- 从C代码出发写系统服务
- 系统服务getSystemService
- Android 关于系统Context.getSystemService(String arg0)获取系统服务的详细剖析-getSystemService
- Android获取系统服务getSystemService与getService区别
- Android-获取服务getContext().getSystemService()
- getSystemService获得系统服务列表
- 从Jni到Java增加一个系统服务SystemServer,并通过getSystemService调用
- LayoutInflater的使用 和getSystemService系统服务
- LayoutInflater的使用 和getSystemService系统服务
- LayoutInflater的使用 和getSystemService系统服务
- Android之getSystemService 各种系统服务总结
- Androidの系统服务之getSystemService
- android中的系统级服务getSystemService(name)
- android getSystemService(系统服务)学习
- new和malloc的区别
- Kafka集群搭建
- ipc(一)无名管道示例
- Qt之qDebug输出转义符反斜杠的问题
- leetcode 236. Lowest Common Ancestor of a Binary Tree
- 从getSystemService()出发获取系统服务
- 第二十五节:父子、兄弟、相邻节点定位方式详解
- 使用Dom4j解析XML
- 电话号码问题
- java面向对象(三)之抽象类,接口
- file error / encoding
- iOS基础知识4
- C# 多线程(lock,Monitor,Mutex,同步事件和等待句柄)
- 自适应和响应式的区别