本文分析了 Android 系统服务通过容器实现单例,确保系统服务的全局唯一。

开发过 Android 的用户肯定都用过这句代码,主要作用是把布局文件 XML 加载到系统中,转换为 Android 的 View:

LayoutInflater layoutInflater = LayoutInflater.from(mContext);

通过以上代码可以拿到 layoutflater 的对象, 然后通过 layoutInflater 就可以把 xml 文件转换为 View 加载到 activity 中,然后操作布局了,那么这个对象是怎么拿到的呢,跟源码。

from() 方法源码:

public static LayoutInflater from(Context context) {

LayoutInflater LayoutInflater =

(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

if (LayoutInflater == null) {

throw new AssertionError("LayoutInflater not found.");

}

return LayoutInflater;

}

可以看到调用了很常见的一句代码: context.getSystemService(), 这句代码应该都用过,调用该方法,传入一个 Context 的常量,可以拿到相对于的 Manager 的对象

经常见到的常量:

WINDOW_SERVICE: 获取 WindowManager 实例

LAYOUT_INFLATER_SERVICE: 获取 LayoutInflater 实例

ACTIVITY_SERVICE: 获取 ActivityManager 实例

ALARM_SERVICE: 获取 AlarmManager 实例

...

跟进 Context 类的这个方法, Context 是个抽象类,该方法是个抽象方法,源码如下:

public abstract class Context {

...

public abstract Object getSystemService(@ServiceName @NonNull String name);

...

}

Context 类的实现类是 ContextImpl , 进入并查找这个方法,源码如下:

@Override

public Object getSystemService(String name) {

return SystemServiceRegistry.getSystemService(this, name);

}

可以看到进入到了 SystemServiceRegistry 类,跟进看源码:

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 是一个 HashMap ,key 是 String, value 是 ServiceFetcher>

private static final HashMap> SYSTEM_SERVICE_FETCHERS =

new HashMap>();

ServiceFetcher> 是一个接口, 有一个方法,是获取 Service

static abstract interface ServiceFetcher {

T getService(ContextImpl ctx);

}

SystemServiceRegistry 源码

// 该类设计成 final 类,防止被继承了。

final class SystemServiceRegistry {

private final static String TAG = "SystemServiceRegistry";

// 注册的服务信息,存入到两个 HashMap 中。

// 两个 HashMap 都是设置为静态的,初始化以后不会再变化的。

private static final HashMap, String> SYSTEM_SERVICE_NAMES =

new HashMap, String>();

private static final HashMap> SYSTEM_SERVICE_FETCHERS =

new HashMap>();

private static int sServiceCacheSize;

// 私有构造方法

private SystemServiceRegistry() { }

// 静态代码块,第一次类加载的时候加载,且只加载一次,保证实例唯一

static {

registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,

new CachedServiceFetcher() {

// createService 该方法只会调用一次,在缓存数组中没有的情况下才会调用,剩下都是从缓存数组中获取的。

@Override

public AccessibilityManager createService(ContextImpl ctx) {

// 调用每个 Manager 的初始化方法

return AccessibilityManager.getInstance(ctx);

}});

registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,

new CachedServiceFetcher() {

@Override

public CaptioningManager createService(ContextImpl ctx) {

return new CaptioningManager(ctx);

}});

registerService(Context.ACCOUNT_SERVICE, AccountManager.class,

new CachedServiceFetcher() {

@Override

public AccountManager createService(ContextImpl ctx) {

IBinder b = ServiceManager.getService(Context.ACCOUNT_SERVICE);

IAccountManager service = IAccountManager.Stub.asInterface(b);

return new AccountManager(ctx, service);

}});

// 此处省略了N多的 registerService() 方法

...

}

/**

* 创建一个数组做缓存,把创建的 service 实例放入到该数组缓存起来

* 该方法在

*/

public static Object[] createServiceCache() {

return new Object[sServiceCacheSize];

}

/**

* 根据常量或者字符串获取指定服务

*/

public static Object getSystemService(ContextImpl ctx, String name) {

ServiceFetcher> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);

return fetcher != null ? fetcher.getService(ctx) : null;

}

/**

* 通过 service 类 获取指定系统服务的名称,(这个方法好像没有用过)

*/

public static String getSystemServiceName(Class> serviceClass) {

return SYSTEM_SERVICE_NAMES.get(serviceClass);

}

/**

* 在静态代码块中会调用到,添加 serviceName 和 serviceClass 到两个 HashMap 中。

*/

private static void registerService(String serviceName, Class serviceClass,

ServiceFetcher serviceFetcher) {

SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);

SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);

}

/**

* Base interface for classes that fetch services.

* These objects must only be created during static initialization.

*/

static abstract interface ServiceFetcher {

T getService(ContextImpl ctx);

}

/**

* 带有缓存的获取 service 抽象类,只要需要加载 service 的时候才初* 始化,相当于实现了单例模式的懒加载方式

*/

static abstract class CachedServiceFetcher implements ServiceFetcher {

private final int mCacheIndex;

public CachedServiceFetcher() {

mCacheIndex = sServiceCacheSize++;

}

@Override

@SuppressWarnings("unchecked")

public final T getService(ContextImpl ctx) {

//

final Object[] cache = ctx.mServiceCache;

synchronized (cache) {

// 查找缓存,没有缓存的话,调用 createService() 初始化一个相关的 service

Object service = cache[mCacheIndex];

if (service == null) {

service = createService(ctx);

cache[mCacheIndex] = service;

}

return (T)service;

}

}

// 实现类需要重写该方法,针对不同的 service 实现不同

public abstract T createService(ContextImpl ctx);

}

...

}

该类上来就是一个静态代码块,在该类加载的时候,初始化了这个代码块,代码块中调用了静态方法 registerService() , 把各个 service 类通过键值对的形式存储到两个 HashMap 中,用户使用的时候,通过 key 获取到 HashMap 中的 ServiceFetcher, 然后调用 ServiceFetcher 的 getService() 方法获取到实例。该方法中,先从数组缓存中查找是否有实例,没有的话,调用 createService 方法,初始化该 service 类,并把该类实例放入到数组缓存中。下次用户再用的时候,会直接返回上次的唯一实例,实现了 Android 系统服务的单例模式。

思考

针对项目的底层服务,需要提供大量单例的,可以采用容器和缓存的方式实现单例模式懒加载方式。通过该方式对项目进行重构和优化。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐