android之Context对各种服务的管理

常常,当我们需要用到服务的时候可以通果Context来获取:Context.getSystemService(name);比如:当我们想知道当前电话状态(来电/去电/sim卡状态等)时候,我们可以通过Context来获取TelephonyManager:

final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

你可知道,为什么可以通过Context来获取各种服务吗?下面来看看.

我们知道,Context的实现类其实是:ContextImpl,所以我们来看看ContextImpl有上面东西.通过代码分析,会很快知道:在ContextImpl中通过工厂模式和单列模式在创建和保存各个服务对象的.比较复杂,所以下面一个一个的介绍:

(1)在ContextImpl中定义如下一个HashMap,

    private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP =  new HashMap<String, ServiceFetcher>();

    这是一个静态的/final的HashMap,其中保存的是每一个服务的ServiceFetcher.其中,String标识当前服务名,ServiceFetcher是这个服务的工具类!其实就是用来创建该服务的对象.

     当我们通过getSystemService(String name)来获取这个服务时候,就是通过这个ServiceFetcher来得到我们需要的服务的:

    public Object getSystemService(String name) {
        ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
        return fetcher == null ? null : fetcher.getService(this);
    }
   如上代码可知:其实是通过 ServiceFetcher的getService()来获取的.

(2)所以我们重点来看看ServiceFetcher实现什么功能,ServiceFetcher其实是一个简单的工厂模式设计思路,并且还使用来单列模式! 当通过getService()来获取服务对象的时候,首先判断这个服务对象是否已经存在:如果已经存在,则立即返回,否则调用他的一个虚的方法createService()来创建,并保存创建的这个服务对象.随意不同服务的ServiceFetcher实现了不同的创建对象的方法createService().这样一来,就可以通过SYSTEM_SERVICE_MAP里面各个服务的ServiceFetcher来获取其对象了.

    /*package*/ static class ServiceFetcher {
        int mContextCacheIndex = -1;

        /**
         * Main entrypoint; only override if you don't need caching.
         */
        public Object getService(ContextImpl ctx) {
            ArrayList<Object> cache = ctx.mServiceCache;
            Object service;
            synchronized (cache) {
                if (cache.size() == 0) {
                    // Initialize the cache vector on first access.
                    // At this point sNextPerContextServiceCacheIndex
                    // is the number of potential services that are
                    // cached per-Context.
                    for (int i = 0; i < sNextPerContextServiceCacheIndex; i++) {
                        cache.add(null);
                    }
                } else {
                    service = cache.get(mContextCacheIndex);
                    if (service != null) {
                        return service;
                    }
                }
                service = createService(ctx);
                cache.set(mContextCacheIndex, service);
                return service;
            }
        }

        /**
         * Override this to create a new per-Context instance of the
         * service.  getService() will handle locking and caching.
         */
        public Object createService(ContextImpl ctx) {
            throw new RuntimeException("Not implemented");
        }
    }

(3)SYSTEM_SERVICE_MAP的初始化.

在ContextImp中,有一段static的代码块,用于初始化所有服务的ServiceFetcher,并且加入SYSTEM_SERVICE_MAP里面.

下面看看电源管理服务的初始化:

        registerService(POWER_SERVICE, new ServiceFetcher() {
                public Object createService(ContextImpl ctx) {
                    IBinder b = ServiceManager.getService(POWER_SERVICE);
                    IPowerManager service = IPowerManager.Stub.asInterface(b);
                    return new PowerManager(ctx.getOuterContext(),
                            service, ctx.mMainThread.getHandler());
                }});
registerService其实是一个static的方法,其主要工作就是:SYSTEM_SERVICE_MAP.put(serviceName, fetcher);


通过上面的分析,可以很好的了解工厂模式和单列模式的混合使用,这样理解没有问题吗?说上面的设计模式为享元模式似乎更合适!当然,不够我觉得不管上面设计模式其实都是一种名称罢了!重要的是知道如何解决实际问题!其实我认为:享元模式就是等于工厂模式+单列模式+(或者还以有其他模式).其中要清楚的是,享元模式的重点在于:共享,不重复.其目的往往时为了解决:大量重复量级的对象使用.





发布了51 篇原创文章 · 获赞 20 · 访问量 12万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章