Android源码中的单例模式
来源:互联网 发布:黄惠康 知乎 编辑:程序博客网 时间:2024/06/05 20:47
最常用的莫过于LayoutInflater类,这些服务都是以单例的方式注入到系统当中的。
我们还是来以LayoutInflater为例。
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; }
看!在from内部调用的还是通过getSystemService方法去获取LayoutInflater.
那这个context又是什么呢?打开context发现它是一个抽象类。
通过阅读一些Google上的资料发现,其实Application、Activity、Service中都会存在Context对象,总数为Activity个数+Service个数+1,
Context是context家族最顶部的一级,其下还有很多实现类:
如图:
Context类本身是一个纯abstract类,它有两个具体的实现子类:ContextImpl和ContextWrapper。
ContextWrapper类,如其名所言,这只是一个包装而、已,ContextWrapper构造函数中必须包含一个真正的Context引用,同时ContextWrapper中提供了attachBaseContext()用于给ContextWrapper对象中指定、真正的Context对象,调用ContextWrapper的方法都会被转向其所包含的真正的Context对象
ContextThemeWrapper类,如其名所言,其内部包含了与主题、(Theme)相关的接口,这里所说的主题就是指在AndroidManifest.xml中通过android:theme为Application元素或者Activity元素指定的主题。当然,只有Activity才需要主题,Service是不需要主题的,因为Service是没有界面的后台场景,所以Service直接继承于ContextWrapper,Application同理。
而ContextImpl类则真正实现了Context中的函数,应用程序中所调用的各种Context类的方法,其实现均来自于该类。
一句话总结:
Context的两个子类分工明确,其中ContextImpl是Context的具体实现类,ContextWrapper是Context的包装类。Activity,Application,Service虽都继承自ContextWrapper(Activity继承自ContextWrapper的子类ContextThemeWrapper),但它们初始化的过程中都会创建ContextImpl对象,由ContextImpl实现Context中的方法。
从这里我们可以知道,ContextImpl才是真正的起决定性作用的类:
ContextImpl是一个内部类,存在与ReceiverRestrictedContext类中
ReceiverRestrictedContext.java:
class ContextImpl extends Context { 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; } }}.....private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP = new HashMap<String, ServiceFetcher>();private static int sNextPerContextServiceCacheIndex = 0;//注册服务private static void registerService(String serviceName, ServiceFetcher fetcher) {if (!(fetcher instanceof StaticServiceFetcher)) {fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;}SYSTEM_SERVICE_MAP.put(serviceName, fetcher);}//根据key获取对应的服务@Overridepublic Object getSystemService(String name) {ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);return fetcher == null ? null : fetcher.getService(this);} static{...registerService(LAYOUT_INFLATER_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext()); }});...(这个静态语句块,在第一次加载该类时执行,里面包含了其他各种服务对象,可以自行googel看源码)}从ReceiverRestrictedContext类的代码来看,在虚拟机第一次加载该类时会注册各种ServiceFatcher,其中就包含了LayoutInflater Serivce;系统将这些服务对象以键值对的形式存储在一个HashMap中,用户使用只需要根据key来获取到对应的ServiceFetcher,接着通过ServiceFecther对象的getService函数来获取具体的服务对象。当第一次获取的时候会通过ServiceFetcher的createService函数自动创建,然后将该对象缓存到一个列表中,下次再取直接从缓存中获取。以上就是用的是容器的方式来实现单例模式的。
参考书籍:
《Android源码设计模式解析与实战》
参考链接:
Context都没弄明白,还怎么做Android开发?
- Android源码中的单例模式
- android 源码中的单例模式
- Android源码中的单例模式
- android源码中的单例模式实现
- Android源码中的单例模式android.util.Singleton
- Android中的单例模式
- Android 中的单例模式
- android中的单例模式
- android中的单例模式
- Android中的设计模式-单例模式
- Android源码分析之单例模式
- Android源码和单例模式
- Android基于源码的单例模式
- Android源码中的一种单例实现
- Android开发中的单例模式
- 单例模式在android中的应用
- 读书笔记--android中的单例模式
- Android中的单例模式使用场景
- 第十二周用递归求最大公约数
- 文件输入输出 c++ 比较两个文本内容
- c++答疑解惑
- wcf序列化和消息编码
- golang chan 单项通道与多项通道
- Android源码中的单例模式
- oracle常用语句
- Java多线程-Thread与Runnable说明
- 使用iText生成doc
- java解析XML文件---SAXReader
- Sublime Text 无法使用Package Control或插件安装失败的解决方法
- 在crontab中执行python脚本系统环境变量问题
- MySql结构语言 ————函数
- Collection 与Collections