经常,当我们须要用到服务的时候能够通果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);

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

android之Context对各种服务的管理的更多相关文章

  1. Android的Context Manager(服务管理器)源码剖析-android学习之旅(99)

    Context Manager介绍 Context Manager对应的进程是servicemanager进程,它先于Service Server和服务客户端运行,进入接收IPC数据的待机状态,处理来 ...

  2. Android的Context && 安卓常用系统服务(当前运行包名/当前网络状态和开关网络/音频服务/马达服务) (转)

    转:http://blog.csdn.net/zhandoushi1982/article/details/8501773 Context字面意思上下文,位于framework 的android.co ...

  3. Android提供的系统服务之--TelephonyManager(电话管理器)

    Android提供的系统服务之--TelephonyManager(电话管理器) 转载请注明出处--coder-pig TelephonyManager的作用: 用于管理手机通话状态,获取电话信息(设 ...

  4. Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7932268 在前面一篇文章中,我们分析了And ...

  5. Android中Context详解

    大家好,  今天给大家介绍下我们在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中时刻的在与它打交道,例如:Service.BroadcastReceiver.A ...

  6. [转] Android应用程序与SurfaceFlinger服务的关系概述和学习计划

    转自:Android应用程序与SurfaceFlinger服务的关系概述和学习计划 SurfaceFlinger服务负责绘制Android应用程序的UI,它的实现相当复杂,要从正面分析它的实现不是一件 ...

  7. Android 使用AIDL调用外部服务

    好处:多个应用程序之间建立共同的服务机制,通过AIDL在不同应用程序之间达到数据的共享和数据相互操作, 本文包括: 1 .创建AIDL 服务端.2 .创建AIDL 客户端. 3.客户端调用服务端提供的 ...

  8. Android中Context详解 ---- 你所不知道的Context

    转自:http://blog.csdn.net/qinjuning/article/details/7310620Android中Context详解 ---- 你所不知道的Context 大家好,  ...

  9. 转:Android中Context详解 ---- 你所不知道的Context

    转:http://blog.csdn.net/qinjuning/article/details/7310620 转:http://blog.csdn.net/lmj623565791/article ...

随机推荐

  1. WPF 自动选择dll,以SQLite为例

    在学习sqlite的过程中,发现它的dll是区分32位和64位的,起初觉得很恼火,但是仔细看了下, 发现让程序自行选择dll其实也不是一件很麻烦的事情,如下: 1>创建一个sqlite数据 2& ...

  2. [论文]A Link-Based Cluster Ensemble Approach for Categorical Data Clustering

    http://www.cnblogs.com/Azhu/p/4137131.html 这篇论文建议先看了上面这一遍,两篇作者是一样的,方法也一样,这一片论文与上面的不同点在于,使用的数据集是目录数据, ...

  3. android基本控件学习-----Button

    Button讲解: 一.在我们实际的使用button的时候经常会对button不同状态会有不同的显示,在讲解Button前,首先对drawable下面的statelistdrawable的相关知识讲一 ...

  4. MMU介绍【转】

    转自:http://blog.csdn.net/martree/article/details/3321578 虚拟存储器的基本思想是程序,数据,堆栈的总的大小可以超过物理存储器的大小,操作系统把当前 ...

  5. iOS关于本地推送

      不多说 直接上代码 
 NSDate *now = [NSDate date]; UILocalNotification *reminderNotification = [[UILocalNoti ...

  6. C#图解教程学习笔记——数据类型与数据存储

    一.数据类型1. 预定义类型C#提供16种预定义类型,包括13种简单类型和3种非简单类型:(1)简单类型<1>11种数值类型: 不同长度的有符号和无符号整数类型 浮点数的float和dou ...

  7. OSX 系统无法直接用 Chrome 双击点击打开本地 html 文件

    在 Mac OS X 下,文件经常会被附加上 OS X 特有的扩展属性 ( extend attributes ),具体表现是用 ls -l 查看时会有 @ 的标记,譬如: $ ls -l index ...

  8. viewpager+fragment出现TransactionTooLargeException的大坑!!!

    最近apk包发给部分测试用户,反馈出现很多崩溃,异常是android.os.TransactionTooLargeException,看表面意思就是传送的数据太大,可是检查代码并没有传输很大的数据啊. ...

  9. 注意这几点,轻轻松松配置 Nginx + Tomcat 的集群和负载均衡

    Tomcat 集群是当单台服务器达到性能瓶颈,通过横向扩展的方式提高整体系统性能的有效手段.Nginx 是一个高性能的 HTTP 和反向代理 web 服务器,可以通过简单的配置实现 Tomcat 集群 ...

  10. 洛谷——P1690 贪婪的Copy

    P1690 贪婪的Copy 题目描述 Copy从卢牛那里听说在一片叫yz的神的领域埋藏着不少宝藏,于是Copy来到了这个被划分为个区域的神地.卢牛告诉了Copy这里共有个宝藏,分别放在第Pi个(1&l ...