同事在进行code review的时候问到我context中的getSystemService方法在哪实现的,他看到了一个ClipBoardManager来进行剪切板存储数据的工具方法中用到了context.getSystemService(),而此处我使用的是Application级别的Context进行调用的,可IDE跳转时发现当前类中的getSystemService()方法竟然是抽象的,Context类就是一个抽象类,没有具体的实现,可在进行调用的时候却一切正常,同事好奇该方法具体实如今哪实现的,因而我俩一块儿看源码和查资料后发现有几个值得注意的地方:java
Note: System services obtained via this API may be closely associated with the Context in which they are obtained from. In general, do not share the service objects between various different contexts (Activities, Applications, Services, Providers, etc.)app
大意: 获取的系统service可能和他们的context有紧密联系,通常来讲不要在不一样的context之间分享服务对象,如Activity、Application、Service、Provideride
明显一样的方法调用的具体实现不一样,从一样拥有getSystemService的Activity的实现能够看到,虽然最终调用仍是从LayoutInflater的context获取工具
/* * Activity中的getSystemService() */ @Override public 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; } // 以上的判断仅仅是为了检查是否为WindowManager获取窗口的服务 return super.getSystemService(name); }
经过super.getSystemService(name)跳转到ContextThemeWrapper这个Context.java类的代理类中,然而也并不是是真正的具体实现,可是在此咱们能够得知LayoutInflater实际上也是获取的是Application级别的全局context,由于该context也是该类中的mBase获取的😄:fetch
@Override public Context getApplicationContext() { return mBase.getApplicationContext(); }
/* * ContextThemeWrapper中的getSystemService() */ @Override public 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); }
最后又追溯到了Context.java中的getSystemService(),什么状况呢,具体实如今哪??一番折腾后,找到了对应的Context实现类:ContextImpl.javathis
@Override public Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name); } @Override public String getSystemServiceName(Class<?> serviceClass) { return SystemServiceRegistry.getSystemServiceName(serviceClass); }
终于SystemServiceRegistry这个类中有了getSystemService的具体实现,调用的方法实际上是getService(),这里三个方法很重要:代理
/** * Creates an array which is used to cache per-Context service instances. */ public static Object[] createServiceCache() { return new Object[sServiceCacheSize]; } /** * 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; } /** * Gets the name of the system-level service that is represented by the specified class. */ public static String getSystemServiceName(Class<?> serviceClass) { return SYSTEM_SERVICE_NAMES.get(serviceClass); } /** * 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); }
能够看出三个方法对service进行了建立、获取和注册。而SystemServiceRegistry这个类负责建立、启动和管理全部的服务,当须要用到哪一个服务的时候,调用到getService方法而后进行名字的索引来找到须要的服务,里面的关键元素:code
在启动APP时进行了必备的service注册,关于注册的服务就不列举了太多了,结构大体如此:component
static { registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class, new CachedServiceFetcher<AccessibilityManager>() { @Override public AccessibilityManager createService(ContextImpl ctx) { return AccessibilityManager.getInstance(ctx); }}); registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class, new CachedServiceFetcher<CaptioningManager>() { @Override public CaptioningManager createService(ContextImpl ctx) { return new CaptioningManager(ctx); }}); registerService(Context.ACCOUNT_SERVICE, AccountManager.class, new CachedServiceFetcher<AccountManager>() { @Override public AccountManager createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(Context.ACCOUNT_SERVICE); IAccountManager service = IAccountManager.Stub.asInterface(b); return new AccountManager(ctx, service); }}); // 代码省略。。。。 }
感兴趣的朋友能够本身看看,进行注册时候是经过HashMap的方式将服务的名字进行了索引存放。对象
上部分的代码中,能够看到有serviceFetcher相关的匿名内部类,每一个服务对应了不一样的实现,所以方法也是抽象的,下面是三个对应的静态抽象内部类和一个接口:
/** * Base interface for classes that fetch services. * These objects must only be created during static initialization. */ static abstract interface ServiceFetcher<T> { T getService(ContextImpl ctx); } /** * 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); } /** * Override this class when the system service does not need a ContextImpl * and should be cached and retained process-wide. */ static abstract class StaticServiceFetcher<T> implements ServiceFetcher<T> { private T mCachedInstance; @Override public final T getService(ContextImpl unused) { synchronized (StaticServiceFetcher.this) { if (mCachedInstance == null) { mCachedInstance = createService(); } return mCachedInstance; } } public abstract T createService(); } /** * Like StaticServiceFetcher, creates only one instance of the service per process, but when * creating the service for the first time, passes it the outer context of the creating * component. * * TODO: Is this safe in the case where multiple applications share the same process? * TODO: Delete this once its only user (ConnectivityManager) is known to work well in the * case where multiple application components each have their own ConnectivityManager object. */ static abstract class StaticOuterContextServiceFetcher<T> implements ServiceFetcher<T> { private T mCachedInstance; @Override public final T getService(ContextImpl ctx) { synchronized (StaticOuterContextServiceFetcher.this) { if (mCachedInstance == null) { mCachedInstance = createService(ctx.getOuterContext()); } return mCachedInstance; } } public abstract T createService(Context applicationContext); }
我俩整个过程花了15分钟就了解了getSystemService的具体调用和实现的方式,仍是源码来得快,在进阶Android开发过程当中,阅读系统和三方类库的源码可以帮咱们事半功倍的效果。