最常用的莫过于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获取对应的服务
@Override
public 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源码设计模式解析与实战》
参考链接:
本文深入剖析了Android中的Context概念,详细介绍了Context的实现机制及其在LayoutInflater等系统服务中的应用。通过对比Context的不同实现类,帮助读者理解Context在Android开发中的核心作用。
579

被折叠的 条评论
为什么被折叠?



