android源码中的单例模式实现
来源:互联网 发布:该域名非本账户域名 编辑:程序博客网 时间:2024/05/18 01:16
源码中好多使用容器实现单例模式:public class Singleton { private static Map<String, Object> objMap = new HashMap<String, Object>(); private Singleton() { } public static void registerService(String key, Object instance) { if (!objMap.containsKey(key)) { objMap.put(key, instance); } } public static Object getService(String key) { return objMap.get(key); }}在程序的初始,将多种单例类型注入到一个统一的管理类中,在使用时根据key获取对象对应类型的对象.这种方式使得我们可以管理多种类型的单例,并且在使用时可以通过统一的接口进行获取操作,降低了耦合度.其实单例的核心原理都是,将构造函数私有化,并且通过静态方法获取一个唯一的实例,在这个获取中必须保证线程安全,防止反序列化导致重新生成实例对象等问题,android源码中的单例模式以常用的LayoutInflater为例:通常在代码中的使用如下: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;}可以看到from函数内部调用的是Context类的getSystemService(String key)方法,Context是一个抽象类,具体实现是在ContextImpl类中,class ContextImpl extends Context { //通过SystemServiceRegistry类来具体实现 @Override public Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name); }}//此类用来管理所有系统服务,可以用{@link Context#getSystemService方法来返回对应的服务final class SystemServiceRegistry { static abstract interface ServiceFetcher<T> { T getService(ContextImpl ctx); } //代码省略 //ServiceFetcher通过getService获取服务对象 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]; //从缓存中读取service对象 if (service == null) { service = createService(ctx); //第一次创建该对象 cache[mCacheIndex] = service; //该对象缓存到一个列表中 } return (T)service; } } public abstract T createService(ContextImpl ctx); //子类复写该方法用以创建服务对象 } //1. services 容器 private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap<String, ServiceFetcher<?>>(); private static int sServiceCacheSize; //2. 注册服务器 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); } //3. 静态语句块 第一次加载该类时执行(只执行一次,确保实例的唯一性) static { //注册 LayoutInflater service registerService(Context.NSD_SERVICE, NsdManager.class, new CachedServiceFetcher<NsdManager>() { @Override public NsdManager createService(ContextImpl ctx) { IBinder b = ServiceManager.getService(Context.NSD_SERVICE); INsdManager service = INsdManager.Stub.asInterface(b); return new NsdManager(ctx.getOuterContext(), service); }}); } //4. 根据key获取对应的服务 public static Object getSystemService(ContextImpl ctx, String name) { //根据name来获取服务 ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name); return fetcher != null ? fetcher.getService(ctx) : null; } //代码省略}从以上代码中可以看到,在虚拟机第一次加载该类时,会注册各种ServiceFetcher,其中就包含了LayoutInflater service,将这些服务以键值对的形式存储在HashMap中,用户使用是只需要根据key来获取对应的ServiceFetcher,然后通过ServiceFetcher对象的getService函数来获取具体的服务对象,当第一次获取是会调用ServiceFetcher的createService函数创建服务对象,然后将该对象缓存到一个列表中,下次再取时直接从缓存中获取,避免重复创建对象,从而达到单例的效果.
2 0
- android源码中的单例模式实现
- Android源码中的单例模式
- android 源码中的单例模式
- Android源码中的单例模式
- Android源码中的一种单例实现
- Android源码中的单例模式android.util.Singleton
- Android中的单例模式
- Android 中的单例模式
- android中的单例模式
- android中的单例模式
- c++单例模式实现源码
- Android中的设计模式-单例模式
- Android源码分析之单例模式
- Android源码和单例模式
- Android基于源码的单例模式
- Android源码中的Builder模式实现
- Swift实现OC中的单例模式
- iOS中的单例模式的实现
- 获取汉字首拼函数(据说该方法来自BCB函数库)
- 第一课: 通过案例对SparkStreaming透彻理解三板斧之一
- 简单粗暴的是时间选择器
- JAVA服务端用友盟给APP(android和IOS)推送消息--转自Carrot_lin
- tinymce编辑器上传图片插件配置
- android源码中的单例模式实现
- 实战编程-字符串编码
- 配置tomcat方法
- busybox配置telnetd
- html中的自闭和标签
- MySQL表级约束与列级约束、修改数据表
- Spring RestTemplate与apache HttpClient
- swift中的assert
- Java 多线程同步的五种方法