zoukankan      html  css  js  c++  java
  • 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);


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





  • 相关阅读:
    qt 计时器自动刷新图片
    qt读取文本
    QLable 显示图片
    QButtonGroup 的使用
    Qt乱码的问题
    wpf 依赖强制回调
    实现Button的动态响应
    C# 闭包对像
    2020新年目标
    捕获、冒泡与阻止事件传播
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6844302.html
Copyright © 2011-2022 走看看