Androd中的单例模式

206 阅读3分钟

作为一个Android开发的老司机,或者刚入行的司机,我觉得你还是有必要学习下Android的单例模式,毕竟单例模式是我们很常用的一个设计模式。

1. 单例模式的几种实现方式

单例模式的写法真的太多了,但是如果你读过Effective Java这本书的话,里面着重推荐的就是使用枚举的方式来实现单例模式。

我们还是要总结单例的实现方式:

  1. 饿汉模式(多线程安全,需要处理反序列化问题)
  2. 饱汉模式(多线程不安全、需要处理反序列化问题)
  3. DCL(高并发会出现DCL检查失效问题)
  4. 静态内部类(多线程安全,需要处理反序列化问题)
  5. 枚举(简单、推荐、防止反序列化)
  6. 使用容器实现单例模式

具体的写法我们不做多的介绍了,要是感兴趣可以自行查询搜索。

2. Android中的单例模式

首先明确一点,Android中的单例模式绝大部分采用了[容器]来实现。

好了,带着这个先入为主的概念,接下来我来带你分析下具体的实现。

2.1 LayoutInflater

单例模式和这个LayoutInflater有关系吗? 恩,是的。

我们首先来回顾下LayoutInflater的使用方式:

    LayoutInflater inflater = LayoutInflater.from(this);


    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;
    }

看来LayoutInflater.from只是系统方便我们使用简化的方法,你看Android的设计者多用心啊。

2.2 分析

// 核心的代码在这里啊
// 因为context只是一个接口,我们必须要追溯到它的实现类ContextImpl才能看到getSystemService方法
LayoutInflater LayoutInflater =
                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

ContextImpl.getSystemService

    @Override
    public Object getSystemService(String name) {
        // 原来是调用了SystemServiceRegistry类的静态方法
        return SystemServiceRegistry.getSystemService(this, name);
    }

SystemServiceRegistry

final class SystemServiceRegistry {
    // 你要的容器类在这里
    private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();


    // 通过该方法来获取service
    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

    
    // 这个是注册服务的方法
    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);
    }

    static {
       
        registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
                new CachedServiceFetcher<ActivityManager>() {
            @Override
            public ActivityManager createService(ContextImpl ctx) {
                return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
            }});

        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);
            }});

        // 我们看到的LayoutInflater就是在这注册的,而且还能知道它的实现类为PhoneLayoutInflater
        registerService(Context.LAYOUT_INFLATER_SERVICE, LayoutInflater.class,
                new CachedServiceFetcher<LayoutInflater>() {
            @Override
            public LayoutInflater createService(ContextImpl ctx) {
                return new PhoneLayoutInflater(ctx.getOuterContext());
            }});


    }



}

通过分析我们知道我们常用的一些Manager都是通过SystemServiceRegistry进行管理的。

  1. 加载SystemServiceRegistry类时,通过静态块加载各种Manager实例到HashMap。
  2. 使用时从HashMap中获取实例,从而实现通过容器来管理单例。

3. 总结

单例模式经常出现在我们的日常开发中,我们对于常规的写法应该都十分熟悉了,那么了解下Android系统的单例实现也算是拓展了一种思路吧。