zoukankan      html  css  js  c++  java
  • Android 源码解析:单例模式-通过容器实现单例模式-懒加载方式

    本文分析了 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 ,keyStringvalueServiceFetcher<?>
        private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
                new HashMap<String, ServiceFetcher<?>>();
    
    • ServiceFetcher<?> 是一个接口, 有一个方法,是获取 Service
        static abstract interface ServiceFetcher<T> {
            T getService(ContextImpl ctx);
        }
    
    • SystemServiceRegistry 源码
    // 该类设计成 final 类,防止被继承了。
    final class SystemServiceRegistry {
        private final static String TAG = "SystemServiceRegistry";
    
        // 注册的服务信息,存入到两个 HashMap 中。
        // 两个 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 int sServiceCacheSize;
    
        // 私有构造方法
        private SystemServiceRegistry() { }
    
        // 静态代码块,第一次类加载的时候加载,且只加载一次,保证实例唯一
        static {
            registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                    new CachedServiceFetcher<AccessibilityManager>() {
                // createService 该方法只会调用一次,在缓存数组中没有的情况下才会调用,剩下都是从缓存数组中获取的。
                @Override
                public AccessibilityManager createService(ContextImpl ctx) {
    
                    // 调用每个 Manager 的初始化方法
                    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);
                }});
            // 此处省略了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 <T> void registerService(String serviceName, Class<T> serviceClass,
                ServiceFetcher<T> 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> {
            T getService(ContextImpl ctx);
        }
    
        /**
         * 带有缓存的获取 service 抽象类,只要需要加载 service 的时候才初* 始化,相当于实现了单例模式的懒加载方式
         */
        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) {
                    // 查找缓存,没有缓存的话,调用 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 系统服务的单例模式。

    思考

    • 针对项目的底层服务,需要提供大量单例的,可以采用容器和缓存的方式实现单例模式懒加载方式。通过该方式对项目进行重构和优化。
  • 相关阅读:
    基本算法2
    基本算法
    读书笔记 《跟老齐学python》
    python杂记 20200207 离线安装 正则
    傻傻分不清之 Cookie、Session、Token、JWT 转载:https://juejin.im/post/5e055d9ef265da33997a42cc
    并发相关 杂记
    原根
    POJ2749 Building roads
    luogu P4735 最大异或和
    SP913 QTREE2
  • 原文地址:https://www.cnblogs.com/liyiran/p/9048462.html
Copyright © 2011-2022 走看看